SQLの窓

2017年09月23日


Android Studio にインポートして使用する SQLite データベースを MDB より作成する VBScript



Windows 64bit 用です。
( ソースを変更すれば、32ビットでももちろん動作します )


Android 内でいろいろするのは大変なので、2005年に作成してずっと使っているテスト用データを SQLite3 に変換する VBScript を改めて最新にしました。

最初の実行で、pragma auto_vacuum = full を実行しているので、いろいろやっても肥大はしないと思います。MDB のアクセスに Microsoft.Jet.OLEDB.4.0 を使用しており、32ビット用の cscript.exe を実行する必要があるので、内部で SysWOW64 を参照しています
( strWinDir と SysWOW64 を省けば 32ビット用になります )

SQLite3 ODBC Driver が必要です

32ビット用の ODBC ドライバが必要になります。ですが、後々の事を考えれば 64 と 32 を両方インストールするのが良いと思います

ODBC ドライバ

ソースコード
Crun()


' 使用する ODBC ドライバです
strDriver = "{SQLite3 ODBC Driver}"

strMDBFile = "販売管理B.mdb"
strSQLiteFile = "hanbai.sqlite3"


' ************************************************
' 基本設定
' ************************************************
' このスクリプトが存在するディレクトリを取得
strCurDir = WScript.ScriptFullName
strCurDir = Replace( strCurDir, WScript.ScriptName, "" )
strMdbPath = strCurDir & strMDBFile
strSQLite3Path = strCurDir & strSQLiteFile

strMessage = "対象 MDB は " & strMdbPath & "です" & vbCrLf & vbCrLf

strMessage = strMessage & "↓SQLiteの環境です" & vbCrLf
strMessage = strMessage & "DB : " & strSQLite3Path & vbCrLf & vbCrLf

strMessage = strMessage & "既にテーブルが存在する場合はメッセージが出ません" & vbCrLf
strMessage = strMessage & "それ以外ではエラーメッセージが出ますが、問題ありません"
if vbCancel = MsgBox( strMessage, vbOkCancel ) then
	Wscript.Quit
end if

' ************************************************
' 処理用文字列設定
' ************************************************
' MDB の接続文字列
strConnectMdb = _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & strMdbPath & ";"

strConnectSQLite3 = _
"Provider=MSDASQL;Driver="&strDriver&";DATABASE=" & strSQLite3Path & ";"

' ************************************************
' 初期処理
' ************************************************
Set Cn = CreateObject("ADODB.Connection")
Cn.CursorLocation = 3
Set Rs = CreateObject( "ADODB.Recordset" )

Set Cn2 = CreateObject("ADODB.Connection")
Cn2.CursorLocation = 3
Set Rs2 = CreateObject( "ADODB.Recordset" )
Rs2.LockType = 3

Cn.Open strConnectMdb
Cn2.Open strConnectSQLite3

RunSS( "pragma auto_vacuum = full" )

' ************************************************
' コード名称マスタ
' ************************************************
Query = _
"create table コード名称マスタ (" & _
"	kubun INT" & _
"	,code VARCHAR(10)" & _
"	,name NVARCHAR(50)" & _
"	,num1 INT" & _
"	,num2 INT" & _
"	,cdate DATETIME" & _
"	,udate DATETIME" & _
"	,primary key(kubun,code)" & _
")"
Call SSTransfer( "コード名称マスタ", Query )

' ************************************************
' コントロールマスタ
' ************************************************
Query = _
"create table コントロールマスタ (" & _
"	ckey VARCHAR(1)" & _
"	,udate DATETIME" & _
"	,uno INT" & _
"	,primary key(ckey)" & _
")"
Call SSTransfer( "コントロールマスタ", Query )

' ************************************************
' メッセージマスタ
' ************************************************
Query = _
"create table メッセージマスタ (" & _
"	code VARCHAR(4)" & _
"	,message NVARCHAR(100)" & _
"	,primary key(code)" & _
")"
Call SSTransfer( "メッセージマスタ", Query )

' ************************************************
' 取引データ
' ************************************************
Query = _
"create table 取引データ (" & _
"	tkubun VARCHAR(2)" & _
"	,uno INT" & _
"	,row INT" & _
"	,tdate DATETIME" & _
"	,tcode VARCHAR(4)" & _
"	,scode VARCHAR(4)" & _
"	,su INT" & _
"	,tanka単価 INT" & _
"	,kin INT" & _
"	,primary key(tkubun,uno,row)" & _
")"
Call SSTransfer( "取引データ", Query )

' ************************************************
' 商品マスタ
' ************************************************
Query = _
"create table 商品マスタ (" & _
"	scode VARCHAR(4)" & _
"	,sname NVARCHAR(50)" & _
"	,ztanka INT" & _
"	,htanka INT" & _
"	,sbun VARCHAR(3)" & _
"	,skubun VARCHAR(1)" & _
"	,cdate DATETIME" & _
"	,udate DATETIME" & _
"	,primary key(scode)" & _
")"
Call SSTransfer( "商品マスタ", Query )

' ************************************************
' 商品分類マスタ
' ************************************************
Query = _
"create table 商品分類マスタ (" & _
"	sbun VARCHAR(3)" & _
"	,name NVARCHAR(50)" & _
"	,cdate DATETIME" & _
"	,udate DATETIME" & _
"	,primary key(sbun)" & _
")"
Call SSTransfer( "商品分類マスタ", Query )

' ************************************************
' 得意先マスタ
' ************************************************
Query = _
"create table 得意先マスタ (" & _
"	tcode VARCHAR(4)" & _
"	,tname NVARCHAR(50)" & _
"	,tkubun VARCHAR(1)" & _
"	,tanto VARCHAR(4)" & _
"	,zip VARCHAR(7)" & _
"	,ad1 NVARCHAR(100)" & _
"	,ad2 NVARCHAR(100)" & _
"	,cdate DATETIME" & _
"	,udate DATETIME" & _
"	,primary key(tcode)" & _
")"
Call SSTransfer( "得意先マスタ", Query )

' ************************************************
' 社員マスタ
' ************************************************
Query = _
"create table 社員マスタ (" & _
"	scode VARCHAR(4)" & _
"	,sname NVARCHAR(50)" & _
"	,furi NVARCHAR(50)" & _
"	,syozoku VARCHAR(4)" & _
"	,sex INT" & _
"	,cdate DATETIME" & _
"	,udate DATETIME" & _
"	,kyuyo INT" & _
"	,teate INT" & _
"	,kanri VARCHAR(4)" & _
"	,primary key(scode)" & _
")"
Call SSTransfer( "社員マスタ", Query )

' ************************************************
' 郵便番号マスタ
' ************************************************
Query = _
"create table 郵便番号マスタ (" & _
"	zip VARCHAR(7)" & _
"	,kana1 NVARCHAR(255)" & _
"	,kana2 NVARCHAR(255)" & _
"	,kana3 NVARCHAR(255)" & _
"	,name1 NVARCHAR(255)" & _
"	,name2 NVARCHAR(255)" & _
"	,name3 NVARCHAR(255)" & _
")"
Call SSTransfer( "郵便番号マスタ", Query )

RunSS( "drop table codename" )
RunSS("alter table コード名称マスタ rename to codename")
RunSS( "drop table control" )
RunSS("alter table コントロールマスタ rename to control")
RunSS( "drop table message" )
RunSS("alter table メッセージマスタ rename to message")
RunSS( "drop table tdata" )
RunSS("alter table 取引データ rename to tdata")
RunSS( "drop table goods" )
RunSS("alter table 商品マスタ rename to goods")
RunSS( "drop table sbun" )
RunSS("alter table 商品分類マスタ rename to sbun")
RunSS( "drop table tokui" )
RunSS("alter table 得意先マスタ rename to tokui")
RunSS( "drop table syain" )
RunSS("alter table 社員マスタ rename to syain")
RunSS( "drop table zip" )
RunSS("alter table 郵便番号マスタ rename to zip")

RunSS( "drop view v_goods" )
Query = _
"create view v_goods as" & _
"	SELECT goods.scode" & _
"	, goods.sname" & _
"	, goods.htanka" & _
"	, sbun.sbun" & _
"	, sbun.name AS bunrui_name" & _
"	, goods.skubun" & _
"	, codename.name AS kubun_name" & _
" from" & _
"	(goods LEFT JOIN sbun" & _
"	ON goods.sbun = sbun.sbun" & _
"	) LEFT JOIN codename" & _
"	ON goods.skubun = codename.code" & _
" where" & _
"	codename.kubun = 3"
RunSS( Query )

' ************************************************
' 終了
' ************************************************

Cn2.Close
Cn.Close

Wscript.Echo "処理が終了しました"

' ************************************************
' 転送
' ************************************************
function SSTransfer( strTable, QueryCreate )

	Wscript.Echo strTable & " の作成を開始します"

	Dim Query

	Query = "drop table " & strTable
	RunSS( Query )

	RunSS( QueryCreate )

	Query = "select * from " & strTable
	Rs.Open Query, Cn
	Rs2.Open Query, Cn2

	nCount = Rs.Fields.Count
	Do While not Rs.EOF
		Rs2.AddNew

		For I = 0 to nCount - 1
			Rs2.Fields(I).Value = Rs.Fields(I).value
		Next
		Rs2.Update

		' 更新
		Rs.MoveNext
	Loop

	Rs2.Close
	Rs.Close

	Wscript.Echo strTable & " の作成が終了しました"

end function

' ************************************************
' SQLLite 実行
' ************************************************
function RunSS( Query )

	on error resume next
	Cn2.Execute Query
	if Err.Number <> 0 then
		Wscript.Echo Err.Description
	end if
	on error goto 0

end function


' **********************************************************
' Cscript.exe で実行を強制
' ウィンドウをアクティブにし、最大化ウィンドウとして表示(3)
' Cscript.exe の実行終了後 pause で一時停止
' **********************************************************
Function Crun( )

	Dim str,WshShell

	str = WScript.FullName
	str = Right( str, 11 )
	str = Ucase( str )
	if str <> "CSCRIPT.EXE" then
		str = WScript.ScriptFullName

		Set WshShell = CreateObject( "WScript.Shell" )
		strWinDir = WshShell.ExpandEnvironmentStrings("%windir%")

		strParam = " "
		For I = 0 to Wscript.Arguments.Count - 1
			if instr(Wscript.Arguments(I), " ") < 1 then
				strParam = strParam & Wscript.Arguments(I) & " "
			else
				strParam = strParam & Dd(Wscript.Arguments(I)) & " "
			end if
		Next
		Call WshShell.Run( "cmd.exe /c " & strWinDir & "\SysWOW64\cscript.exe " & Dd(str) & strParam & " & pause", 3 )
		WScript.Quit
	end if

End Function
' **********************************************************
' 文字列を " で囲む関数
' **********************************************************
Function Dd( strValue )

	Dd = """" & strValue & """"

End function


Androd には、初回データベースを一つ作成してデータベース用のフォルダを作成させて Push するといいです。

SQLite 用クラス
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class MySQLite extends SQLiteOpenHelper {

	// *********************************
	// コンストラクタ
	// *********************************
	public MySQLite(Context context, String dbfile, int dbversion) {
		super(context, dbfile, null, dbversion);
	}

	@Override
	public void onCreate(SQLiteDatabase sqLiteDatabase) {

	}

	@Override
	public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

	}
}


db 作成およびテスト用コード
public class MainActivity extends AppCompatActivity {

	private MySQLite mySQLite;
	private SQLiteDatabase db;
	private ContentValues values;
	int counter;

	@Override
	protected void onStart() {
		super.onStart();
		Log.i("lightbox", "onStart");

		mySQLite = new MySQLite(MainActivity.this,"hanbai.sqlite3",1);
		// 書き込み用
		db = mySQLite.getWritableDatabase();
		// データ書き込み用
		values = new ContentValues();
		counter = 50;

	}

	@Override
	protected void onStop() {
		super.onStop();
		Log.i("lightbox", "onStop");

		db.close();
		mySQLite.close();

	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);


		MainActivity.this.findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {

				counter++;
				values.put("scode", String.format("%04d", counter));
				values.put("sname", String.format("氏名%d", counter));
				values.put("kyuyo", counter*1000);
				db.insert("syain", null, values);

				Log.i("lightbox", String.format("%d",counter));

			}
		});

		MainActivity.this.findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {

				String sql = String.format("select * from %s order by scode desc", "syain");
				Cursor cursor = mySQLite.getReadableDatabase().rawQuery(sql, null);
				Boolean isData = null;
				while ( isData == null ? (isData = cursor.moveToFirst()) : (isData = cursor.moveToNext()) ) {

					String scode = cursor.getString(cursor.getColumnIndex("scode"));
					String sname = cursor.getString(cursor.getColumnIndex("sname"));

					Log.i("lightbox", String.format("%s : %s",scode,sname));

				}
				cursor.close();

			}
		});



	}
}




posted by lightbox at 2017-09-23 16:14 | 2017 Android Studio | このブログの読者になる | 更新情報をチェックする

ViewSwitcher を使用した2画面アプリ (3) : 画面部分の作成と画面切り替えテスト『画面をコントロールする Helper クラスの作成』

この内容は、ViewSwitcher を使用した2画面アプリ (2) : 画面部分の作成と画面切り替えテスト『画面の作成』より続いています。
Helper クラスはその名の通り、『お助けクラス』です。一般的には『標準化』の為の部品です。名称はなんでもいいですが、ここでは一般名として『Helper』と名乗っています。 通常、省略せずに画面まわりのコードを書こうとすると指定しているのは id だけなのに、やたらと長いコードを書くはめになります。また、アプリが完成してから眺めてみると、相当無駄が多いことも多くなります。 ここでは、まず最初からその無駄を省くための画面周りのメソッドを作成した Helper クラスをプロジェクトに追加します。 Helper クラスを作成すると、画面切り替えのテストは以下の MainActivity で行えます
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends AppCompatActivity {

	public Helper helper;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		helper = new Helper(MainActivity.this);

	}

	// *******************************
	// メニュー
	// *******************************
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.menu_main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		int id = item.getItemId();

		if (id == R.id.action_1) {
			Log.i("lightbox","処理1");

			helper.showFirstView();

			return true;
		}

		if (id == R.id.action_2) {
			Log.i("lightbox","処理2");

			helper.showInsertView();

			return true;
		}

		return super.onOptionsItemSelected(item);
	}
}

※ メニュー部分も省略したい場合は、MainActivity を継承したクラス( 例えば、MainControl )を作って、それをマニフェストで初期画面にするといいです。

Helper.java

※ コピペしやすいように、先頭のパッケージ部分を省いています

とても単純なコードが並んでいます。これらは本来 MainActivity で記述していたものを引越ししただけのものです。なので、このプロジェクトでしか使えませんが、『標準化』のサンプルにはなると思います。

確認ダイアログ処理に関しても、MainActivity に書くと、『ただ確認したいだけで機能とは関係無い』のに、とても多くの行数を必要とします。ただ、処理的には、確認後の処理は MainActivity で記述したいので、OnDialogOkListener を作って使用しています。(ボタンのクリック処理と同じです)

※ 商品では無いので(テストしたいだけなので)、フラグメントとかも無しです
import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.ViewSwitcher;

public class Helper {

	private MainActivity mainActivity;
	private ViewSwitcher viewSwitcher;

	// *******************************
	// 確認ダイアログ用
	// *******************************
	private AlertDialog.Builder alertDialogBuilder;

	// *******************************
	// 確認ダイアログ用インターフェイス
	// *******************************
	public interface OnDialogOkListener {
		abstract public void onDialogOkListener();
	}

	// *******************************
	// コンストラクタ
	// *******************************
	public Helper(MainActivity mainActivity) {

		this.mainActivity = mainActivity;
		this.viewSwitcher = (ViewSwitcher) mainActivity.findViewById(R.id.viewSwitcher);

		initSettings();
	}

	// *******************************
	// 初期処理
	// ******************************
	public void initSettings() {

		mainActivity.setTitle("社員一覧");

	}

	// *******************************
	// 確認ダイアログ処理
	// ******************************
	public void showDialog( String message, final OnDialogOkListener listener ) {

		Log.i("lightbox", "showDialog");

		alertDialogBuilder = new AlertDialog.Builder(mainActivity);
		alertDialogBuilder.setTitle("確認");
		alertDialogBuilder.setMessage(message);

		alertDialogBuilder.setPositiveButton("OK",
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						Log.i("lightbox", "OK");

						listener.onDialogOkListener();

					}
				});

		alertDialogBuilder.setOnCancelListener(new DialogInterface.OnCancelListener() {
			@Override
			public void onCancel(DialogInterface dialog) {
				Log.i("lightbox", "CANCEL");
			}
		});

		// キャンセル可能
		alertDialogBuilder.setCancelable(true);
		alertDialogBuilder.show();

	}

	// *******************************
	// 初期画面
	// *******************************
	public void showFirstView() {

		// コード表示部分の表示
		Helper.this.getTextView(R.id.textViewCode).setVisibility(View.VISIBLE);
		// コード入力部分の非表示
		Helper.this.getEditText(R.id.editTextCode).setVisibility(View.GONE);
		mainActivity.setTitle("社員一覧");
		viewSwitcher.setDisplayedChild(0);

	}

	// *******************************
	// 修正画面
	// *******************************
	public void showEditView() {

		// コード表示部分の表示
		Helper.this.getTextView(R.id.textViewCode).setVisibility(View.VISIBLE);
		// コード入力部分の非表示
		Helper.this.getEditText(R.id.editTextCode).setVisibility(View.GONE);
		mainActivity.setTitle("社員修正");
		viewSwitcher.setDisplayedChild(1);

	}

	// *******************************
	// 新規画面
	// *******************************
	public void showInsertView() {

		// コード表示部分の表示
		Helper.this.getTextView(R.id.textViewCode).setVisibility(View.GONE);
		// コード入力部分の非表示
		Helper.this.getEditText(R.id.editTextCode).setVisibility(View.VISIBLE);
		mainActivity.setTitle("社員登録");
		Helper.this.setEditTextString(R.id.editTextCode,"");
		Helper.this.setEditTextString(R.id.editText1,"");
		Helper.this.setEditTextString(R.id.editText2,"");
		viewSwitcher.setDisplayedChild(1);

	}

	// *******************************
	// EditText 取得
	// *******************************
	public EditText getEditText(int id) {
		return (EditText)mainActivity.findViewById(id);
	}

	// *******************************
	// TextView 取得
	// *******************************
	public TextView getTextView(int id) {
		return (TextView)mainActivity.findViewById(id);
	}

	// *******************************
	// TextView より値取得
	// *******************************
	public String getTextViewString(int id) {
		return ((TextView)mainActivity.findViewById(id)).getText().toString();
	}

	// *******************************
	// EditText より入力値取得
	// *******************************
	public String getEditTextString(int id) {
		return ((EditText)mainActivity.findViewById(id)).getText().toString();
	}

	// *******************************
	// EditText に値セット
	// *******************************
	public void setEditTextString(int id,String text) {
		((EditText)mainActivity.findViewById(id)).setText(text);
	}

}





posted by lightbox at 2017-09-23 15:07 | 2017 Android Studio | このブログの読者になる | 更新情報をチェックする

ViewSwitcher を使用した2画面アプリ (2) : 画面部分の作成と画面切り替えテスト『画面の作成』

この内容は、ViewSwitcher を使用した2画面アプリ (1) : 画面部分の作成と画面切り替えテスト『メニューの作成』より続いています。
ViewSwitcher 上で二つのレイアウトを作成し、ViewSwitcher のメソッドを使用してそのレイアウトを切り替えます。そのまま全てを一つの画面定義に記述してもいいのでが、そうすると2画面目の内容を『デザイナ』で確認する事ができません。 ですから、2画面目は別の画面定義で作成して、include で ViewSwitcher の中から呼び出すようにします。 activity_main.xml 画面の切り替えは、一般的には ViewAnimator クラスの showNext() と showPrevious() を使うのですが、実行するのがメニューなので、どこで実行しても正しい画面が表示されるように、setDisplayedChild(int whichChild) を使用します( whichChild は 0 かまたは 1 ) 多少無駄な動きは存在しますが、簡単に正しく動作するはずです。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:padding="16dp">

    <ViewSwitcher
        android:id="@+id/viewSwitcher"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ListView
                android:id="@+id/listView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>

        </LinearLayout>

        <include
            android:id="@+id/entry"
            layout="@layout/entry"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

    </ViewSwitcher>

</LinearLayout>





entry.xml

editTextCode と textViewCode と  は、社員マスタのキー部分に使用します。機能としては、修正処理と新規登録処理の二つあるので、それぞれ editTextCode と textViewCode を使い、使用しないほうは setVisibility(View.GONE); で非表示にします
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <TextView
        android:id="@+id/textViewCode"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="4dp"
        android:textSize="30sp"/>

    <EditText
        android:id="@+id/editTextCode"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textPersonName"/>

    <EditText
        android:id="@+id/editText1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textPersonName"/>

    <EditText
        android:id="@+id/editText2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textPersonName"/>

    <Button
        android:id="@+id/buttonUpdate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="更新"/>

</LinearLayout>





posted by lightbox at 2017-09-23 14:33 | 2017 Android Studio | このブログの読者になる | 更新情報をチェックする

ViewSwitcher を使用した2画面アプリ (1) : 画面部分の作成と画面切り替えテスト『メニューの作成』

この内容は、ViewSwitcher を使用した2画面アプリ (2) : 画面部分の作成と画面切り替えテスト『画面の作成』に続いています。
2画面アプリと言えば、もう一つの Activity を作成して、Intent でデータを引き渡すタイプですが、初心者にとってちょっと敷居が高いので、ViewSwitcher を使用します。ViewSwitcher は2画面のみ対応ですが、同系統(ViewAnimator を継承)の ViewFlipper を使用すれば複数画面も簡単に作成できます。 この場合、見えている画面は一つでも常に同じ Activity で画面を参照できるので、大きな画面に全て表示されていると思って普通にコードが書けます。ですから、そこが楽なぶん、Helper クラスを作成して、画面の処理は全てそこにまかせるという工夫に力を入れたいと思います。 1) メニューの作成 メニューは、その場面で必要な画面切替えに使用します。画面上に機能に直接関係無いボタンを作りたく無いので作成します。Android Studio のテンプレートとしては 『Empty』を使用しますかので、メニュー部分は自分で作成する必要があります。 ▼ menu フォルダの作成 (最後に OK で menu フォルダがリソースに作成されます) ▼ メニューフォルダで、new => Menu resource file でメニュー定義を作成 メニューのファイル名は、何でもいいですが、通常の画面と同じく XML で作成されるので、小文字のアルファベットで、word 間は _(アンダーバー)を使います。ここでは、Android が一般的に使う 『menu_main』を使用しています メニューアイテムの追加 デザイナの画面に、MenuItem をドラッグ&ドロップして追加します。左下の『コンポーネント・ツリー』は動作しないので注意です。 次に右サイドの『プロパティ』で、id を入力します。icon と showAsAction は自由に選択してもいいのですが、ここでは以下のようにエディタで定義します
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
      xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/action_1"
        android:icon="@android:drawable/btn_dialog"
        android:title="戻る"
        app:showAsAction="always"/>

    <item
        android:id="@+id/action_2"
        android:title="新規登録"/>

</menu>



メニューの実行部分の作成

機能的には一度作ってしまえば変更する事は殆ど無いので、MainActivity の最後に追加します。(helper のメソッドは後で作成するのでコメントにしています)
	// *******************************
	// メニュー
	// *******************************
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.menu_main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		int id = item.getItemId();

		if (id == R.id.action_1) {
			Log.i("lightbox","処理1");

			// helper.showFirstView();

			return true;
		}

		if (id == R.id.action_2) {
			Log.i("lightbox","処理2");

			// helper.showInsertView();

			return true;
		}

		return super.onOptionsItemSelected(item);
	}



posted by lightbox at 2017-09-23 13:10 | 2017 Android Studio | このブログの読者になる | 更新情報をチェックする

2017年09月19日


System.Data.OleDb で select into 構文を使って簡単に Microsoft Access のデータを他の データベースにエクスポートする

結論から言うと、System.Data.OleDb と ADO で Microsoft Access に接続すると同等の処理ができます。元々、ADO で可能だった処理を System.Data.OleDb で可能かどうか確認し、System.Data.Odbc でとこまで同じ事が可能か試してみました。

結果的に、System.Data.Odbc では ODBC の動的接続では処理不可で、DSN を作成すると可能でした。

テスト用コード
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Odbc;
using System.Data.OleDb;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace OdbcAccessTest {
	public partial class Form1 : Form {

		// *************************************
		// System.Data.Odbc
		// *************************************
		private OdbcConnection myCon;
		private OdbcCommand myCommand;
		private OdbcDataReader myReader;

		// *************************************
		// System.Data.OleDb
		// *************************************
		private OleDbConnection myConAccess;

		// *************************************
		// ADO
		// *************************************
		private dynamic objAdoCon;

		public Form1() {
			InitializeComponent();
		}

		// *************************************
		// System.Data.Odbc で Access データの読み込み
		// *************************************
		private void button1_Click(object sender, EventArgs e) {

			string myQuery = "SELECT * from 社員マスタ";

			using (myCommand = new OdbcCommand()) {
				// 実行する為に必要な情報をセット
				myCommand.CommandText = myQuery;
				myCommand.Connection = myCon;

				using (myReader = myCommand.ExecuteReader()) {

					// 読み出し

					while (myReader.Read()) {
						// 文字列
						Console.Write(GetValue(myReader, "社員コード") + " : ");
						Console.Write(GetValue(myReader, "氏名") + " : ");
						Console.Write(GetValue(myReader, "フリガナ") + " : ");
						// 整数
						Console.Write(GetValue(myReader, "給与") + " : ");
						Console.Write(GetValue(myReader, "手当") + " : ");
						// 日付
						Console.Write(GetValue(myReader, "作成日") + " : ");
						Console.Write(GetValue(myReader, "更新日") + " : ");

						Console.WriteLine();

					}

					myReader.Close();
				}

			}

		}

		// *************************************
		// テスト用簡易列データ取得
		// *************************************
		private string GetValue(OdbcDataReader myReader, string p) {

			string ret = "";
			int fld = 0;

			// 指定された列名より、テーブル内での定義順序番号を取得
			fld = myReader.GetOrdinal(p);
			// 定義順序番号より、NULL かどうかをチェック
			if (myReader.IsDBNull(fld)) {
				ret = "";
			}
			else {
				// NULL でなければ内容をオブジェクトとして取りだして文字列化する
				ret = myReader.GetValue(fld).ToString();
			}

			// 列の値を返す
			return ret;
		}

		// *************************************
		// 接続処理
		// *************************************
		private void Form1_Load(object sender, EventArgs e) {

			// *************************************
			// System.Data.Odbc
			// *************************************
			OdbcConnectionStringBuilder builder = new OdbcConnectionStringBuilder();

			builder.Driver = "Microsoft Access Driver (*.mdb, *.accdb)";
			builder.Add("dbq", @"C:\tmp\販売管理C.accdb");
			// 内容を確認
			Console.WriteLine(builder.ConnectionString);

			// 新しい OdbcConnection オブジェクトを作成
			myCon = new OdbcConnection();

			// 接続文字列を設定
			myCon.ConnectionString = builder.ConnectionString;

			// 接続を開く
			try {
				myCon.Open();
			}
			catch (OdbcException ex) {
				MessageBox.Show(this, "接続エラーです:" + ex.Message);
			}

			// *************************************
			// System.Data.OleDb
			// *************************************
			myConAccess = new OleDbConnection();
			myConAccess.ConnectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};", @"C:\tmp\販売管理C.accdb");
			// 接続を開く
			try {
				myConAccess.Open();
			}
			catch (Exception ex) {
				MessageBox.Show(this, "接続エラーです:" + ex.Message);
			}
	
			// *************************************
			// ADO
			// *************************************
			objAdoCon = Activator.CreateInstance(Type.GetTypeFromProgID("ADODB.Connection"));

			string connectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\tmp\001\販売管理C.accdb;";
			try {
				objAdoCon.Open(connectionString);
			}
			catch (Exception ex) {
				MessageBox.Show(this, ex.Message);
			}
		}

		// *************************************
		// 接続解除
		// *************************************
		private void Form1_FormClosed(object sender, FormClosedEventArgs e) {

			myCon.Close();
			myConAccess.Close();
			objAdoCon.Close();

		}

		// *************************************
		// System.Data.OleDb
		// *************************************
		private void button2_Click(object sender, EventArgs e) {

			string myQuery;

			myQuery = @"select * into [Excel 8.0;DATABASE=c:\tmp\販売管理C.xls].商品マスタ_OleDb from 商品マスタ";
			//myQuery = @"select * into [Excel 12.0 xml;DATABASE=c:\tmp\販売管理C.xlsx].商品マスタ_OleDb from 商品マスタ";
			//myQuery = @"select * into [;DATABASE=C:\tmp\データベース1.accdb].商品マスタ_OleDb from 商品マスタ";
			//myQuery = @"select * into [;DATABASE=C:\tmp\データベース1.mdb].商品マスタ_OleDb from 商品マスタ";
			//myQuery = @"select * into [ODBC;DSN=SQS64;Database=lightbox;UID=sa;PWD=password].商品マスタ_OleDb from 商品マスタ";
			//myQuery = @"select * into [ODBC;DSN=SQS32;Database=lightbox;UID=sa;PWD=password].商品マスタ_OleDb from 商品マスタ";
			//myQuery = @"select * into [ODBC;DSN=MYSQL32;Database=lightbox;UID=root;PWD=password].商品マスタ_OleDb from 商品マスタ";
			//myQuery = @"select * into [ODBC;Driver={SQL Server Native Client 11.0};server=layla;database=lightbox;uid=sa;pwd=password].商品マスタ_OleDb from 商品マスタ";
			//myQuery = @"select * into [ODBC;Driver={MySQL ODBC 5.3 Unicode Driver};server=layla;database=lightbox;uid=root;pwd=password].商品マスタ_OleDb from 商品マスタ";

			using (OleDbCommand myCommand = new OleDbCommand()) {

				// *********************
				// 接続
				// *********************
				try {
					// コマンドオブジェクトに接続をセット
					myCommand.Connection = myConAccess;
					myCommand.CommandText = myQuery;
					myCommand.ExecuteNonQuery();

				}
				catch (Exception ex) {
					MessageBox.Show(this, ex.Message);
				}
			}

		}

		// *************************************
		// System.Data.Odbc
		// *************************************
		private void button3_Click(object sender, EventArgs e) {

			string myQuery;

			myQuery = @"select * into [Excel 8.0;DATABASE=c:\tmp\販売管理C.xls].商品マスタ_Odbc from 商品マスタ";
			//myQuery = @"select * into [Excel 12.0 xml;DATABASE=c:\tmp\販売管理C.xlsx].商品マスタ_Odbc from 商品マスタ";
			//myQuery = @"select * into [;DATABASE=C:\tmp\データベース1.accdb].商品マスタ_Odbc from 商品マスタ";
			//myQuery = @"select * into [;DATABASE=C:\tmp\データベース1.mdb].商品マスタ_Odbc from 商品マスタ";
			//myQuery = @"select * into [ODBC;DSN=SQS64;Database=lightbox;UID=sa;PWD=password].商品マスタ_Odbc from 商品マスタ";
			//myQuery = @"select * into [ODBC;DSN=SQS32;Database=lightbox;UID=sa;PWD=password].商品マスタ_Odbc from 商品マスタ";
			//myQuery = @"select * into [ODBC;DSN=MYSQL32;Database=lightbox;UID=root;PWD=password].商品マスタ_Odbc from 商品マスタ";

			using (myCommand = new OdbcCommand()) {

				try {
					// コマンドオブジェクトに接続をセット
					myCommand.Connection = myCon;
					myCommand.CommandText = myQuery;
					myCommand.ExecuteNonQuery();
				}
				catch (Exception ex) {
					MessageBox.Show(this, ex.Message);
				}
			}

		}

		// *************************************
		// ADO を使う場合
		// *************************************
		private void button4_Click(object sender, EventArgs e) {

			string myQuery;

			myQuery = @"select * into [Excel 8.0;DATABASE=c:\tmp\販売管理C.xls].商品マスタ_ADO from 商品マスタ";
			//myQuery = @"select * into [Excel 12.0 xml;DATABASE=c:\tmp\販売管理C.xlsx].商品マスタ_ADO from 商品マスタ";
			//myQuery = @"select * into [;DATABASE=C:\tmp\データベース1.accdb].商品マスタ_ADO from 商品マスタ";
			//myQuery = @"select * into [;DATABASE=C:\tmp\データベース1.mdb].商品マスタ_ADO from 商品マスタ";
			//myQuery = @"select * into [ODBC;DSN=SQS64;Database=lightbox;UID=sa;PWD=password].商品マスタ_ADO from 商品マスタ";
			//myQuery = @"select * into [ODBC;DSN=SQS32;Database=lightbox;UID=sa;PWD=password].商品マスタ_ADO from 商品マスタ";
			//myQuery = @"select * into [ODBC;DSN=MYSQL32;Database=lightbox;UID=root;PWD=password].商品マスタ_ADO from 商品マスタ";
			//myQuery = @"select * into [ODBC;Driver={SQL Server Native Client 11.0};server=layla;database=lightbox;uid=sa;pwd=password].商品マスタ_ADO from 商品マスタ";
			//myQuery = @"select * into [ODBC;Driver={MySQL ODBC 5.3 Unicode Driver};server=layla;database=lightbox;uid=root;pwd=password].商品マスタ_ADO from 商品マスタ";

			try {
				objAdoCon.Execute(myQuery);
			}
			catch (Exception ex) {
				MessageBox.Show(this, ex.Message);
			}

		}

	}
}

ここでは、into 側の表で使用していますが、from 側の表でも使用できるはずです。エクスポートは高速で実行されますが、キーの定義はエクスポートされないので、後から定義する必要があります。

SQL 一覧
@"select * into [Excel 8.0;DATABASE=c:\tmp\販売管理C.xls].商品マスタ_ADO from 商品マスタ";
@"select * into [Excel 12.0 xml;DATABASE=c:\tmp\販売管理C.xlsx].商品マスタ_ADO from 商品マスタ";
@"select * into [;DATABASE=C:\tmp\データベース1.accdb].商品マスタ_ADO from 商品マスタ";
@"select * into [;DATABASE=C:\tmp\データベース1.mdb].商品マスタ_ADO from 商品マスタ";
@"select * into [ODBC;DSN=SQS64;Database=lightbox;UID=sa;PWD=password].商品マスタ_ADO from 商品マスタ";
@"select * into [ODBC;DSN=SQS32;Database=lightbox;UID=sa;PWD=password].商品マスタ_ADO from 商品マスタ";
@"select * into [ODBC;DSN=MYSQL32;Database=lightbox;UID=root;PWD=password].商品マスタ_ADO from 商品マスタ";
@"select * into [ODBC;Driver={SQL Server Native Client 11.0};server=layla;database=lightbox;uid=sa;pwd=password].商品マスタ_ADO from 商品マスタ";
@"select * into [ODBC;Driver={MySQL ODBC 5.3 Unicode Driver};server=layla;database=lightbox;uid=root;pwd=password].商品マスタ_ADO from 商品マスタ";


外部参照部分一覧
[Excel 8.0;DATABASE=c:\tmp\販売管理C.xls].テーブル名
[Excel 12.0 xml;DATABASE=c:\tmp\販売管理C.xlsx].テーブル名
[;DATABASE=C:\tmp\データベース1.accdb].テーブル名
[;DATABASE=C:\tmp\データベース1.mdb].テーブル名
[ODBC;DSN=SQS64;Database=lightbox;UID=sa;PWD=password].テーブル名
[ODBC;DSN=SQS32;Database=lightbox;UID=sa;PWD=password].テーブル名
[ODBC;DSN=MYSQL32;Database=lightbox;UID=root;PWD=password].テーブル名
[ODBC;Driver={SQL Server Native Client 11.0};server=layla;database=lightbox;uid=sa;pwd=password].テーブル名
[ODBC;Driver={MySQL ODBC 5.3 Unicode Driver};server=layla;database=lightbox;uid=root;pwd=password].テーブル名

Excel と Microsoft Access は特殊ですが、ODBC は同じ書式なので他の DB にも使用可能なはずです。接続パラメータは、実際 DSN を作成してから、レジストリを見れば必要なものが全て書かれています。

▼ エクスポートでは使えませんが、以下は Excel を ODBC で定義した場合の例です


PHP で ODBC 接続するとなると、上記データを使って以下のようになります
$ms_excel = "./data/syain.xls";
$ms_excel = realpath($ms_excel);
$excel_dir = dirname($ms_excel);
$connect_string = "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};dbq={$ms_excel};DefaultDir={$excel_dir};FIL=Excel 8.0;DriverID=790";$user="";$pass="";




posted by lightbox at 2017-09-19 00:48 | VS(C#) | このブログの読者になる | 更新情報をチェックする

2017年09月09日


OkHttp を使用した HttpAccess クラスで Web 上の 画像をダウンロードして表示するテンプレート

▼ HttpAccess パッケージのダウンロード


( 解凍して、main\java フォルダの中に コピーして下さい )
※ OkHttp より 最新の Gradle の記述を取得して build.gradle の dependencies の最後に貼り付けて下さい
例) compile 'com.squareup.okhttp3:okhttp:3.8.1'

処理概要

ボタンをクリックした後、HttpAccess クラスでファイルをダウンロードする download メソッドを実行するテンプレートです。サンプルでは画像を使用して、ダウンロードした後に ImageView に表示していますが、ダウンロード処理だけならば、どのようなファイルでもかまいません。

ここでは、パッケージ内に保存していますが、OutputStream を引き渡すので、他の保存場所でも問題はありません。

※ onAsyncTaskListener の引数の文字列は、http のステータスコードなので、通常は 200 が返ります。インターネットのアクセスそのものが成功すれば、null 以外が返ります。

MainActivity
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;

import com.example.lightbox.web.HttpAccess;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class MainActivity extends AppCompatActivity {

	private HttpAccess httpAccess;
	private ImageView imageView;
	private String image_url;
	private OutputStream outputStream;

	private Bitmap bitmap;
	private BitmapFactory.Options options;

	private InputStream inputStream;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		// ダウンロードでは、URL をメソッドで指定します
		httpAccess = new HttpAccess("");
		imageView = (ImageView) MainActivity.this.findViewById(R.id.imageView);
		image_url = "https://lightbox.sakura.ne.jp/demo/image/sample.jpg";

		// ボタンをクリック
		MainActivity.this.findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {

				try {

					// 保存ファイル
					outputStream = MainActivity.this.openFileOutput("save.jpg", MODE_PRIVATE);
					// ダウンロード
					httpAccess.download(image_url,outputStream, new HttpAccess.OnAsyncTaskListener() {
						@Override
						public void onAsyncTaskListener(String s) {

							if ( s != null ) {
								Toast.makeText(MainActivity.this,"画像が保存されました",Toast.LENGTH_SHORT).show();

								// ステータスコード
								Log.i("lightbox", String.format("code = %s",s));

								// 画像を読み込む
								bitmap = null;
								try {
									options = new BitmapFactory.Options();
									inputStream = MainActivity.this.openFileInput("save.jpg");
									bitmap = BitmapFactory.decodeStream(inputStream, null, options);	// ここではオプションは未指定
									inputStream.close();

								} catch (IOException e) {
									e.printStackTrace();
								}

								// 表示
								if ( bitmap != null ) {
									imageView.setImageBitmap(bitmap);
								}
							}
						}
					});

				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

}


画面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              xmlns:tools="http://schemas.android.com/tools"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical"
              tools:context=".MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

※ android.permission.INTERNET が必要です
※ コピーして使いやすいように、ソースコードにパッケージに依存する記述が無いので注意して下さい。
(画面は、.MainActivity なのでそのまま使用可能です)



posted by lightbox at 2017-09-09 16:57 | 2017 Android Studio | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します
container 終わり



フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり