2016年11月18日金曜日

お知らせ:ブログの移転

当ブログをご覧いただき、誠にありがとうございます。

 この度、当ブログを以下のURL(ユニリタホームページ)に移転しました!

 移転先でも引き続きご覧いただければ幸いです。

 ↓↓
http://www.unirita.co.jp/blog/data-utilization/data-linkage/

2016年8月10日水曜日

Microsoft Office と Microsoft Access ODBCドライバ を共存させた環境を Windows 10にアップデートしてしばらくしたら、Excelの起動時に見たことの無いエラーを出すようになった場合

こんにちは。近藤です。



Windows 10への無償アップデート期間も終了し、多くのかたのOSがWindows 10になっているのではないでしょうか?
Windows 10にアップデートしても、アップデート前のOSで使用していたほとんどのアプリケーションはそのまま使えていると思います。

ですが、一部変わっているものもあり、「32ビット版Microsoft Officeが導入されている64ビット版Windows環境に、64ビット版Microsoft Access ODBCドライバを導入」した環境で、Officeにパッチがあたると出現するダイアログでは、出力されるダイアログボックスが1つ増えています。



この1つめの警告ダイアログボックス、初めて見るとメッセージの意味がわからず、また、OKを押して再セットアップしても解決しないので驚くのですが、
「Officeが導入されている環境でも、前回説明した「/passive」オプションを付けたインストールができそうな感じがするのですが、残念ながらそれだけではOfficeの起動時に再設定を行うためのセットアップダイアログが毎回出るようになってしまいます。」(記事「32ビット版Microsoft Officeが導入されている64ビット版Windows環境に、64ビット版Microsoft Access ODBCドライバを導入する方法」より)
これと同じ状況です。

ですので、このときの記事を参考に、レジストリを確認し、修正してください。


2016年8月9日火曜日

Windowsのコマンド実行でメール送信(BASP21)

こんにちは。近藤です。


以前の担当回で、コマンドからメールを送信する例として、WSHで記載した例PowerShellで記載した例を掲載しました。2例のように、Windowsの機能のみでメール送信できるのですが、Windows環境では、BASP21も多く利用されています。BASP21は、メール送受信のための汎用コンポーネントで、ライセンスフリーで公開されています。今回は、BASP21を使って書いた例を記載します。


やりかた:

BASP21を使用してメールを送信する例を記載します。
今回は、WSHを使用した例を記載します。

0.(事前準備)BASP21を、利用環境にインストールします。(手順は省略します)

1.以下のスクリプトファイルを作成します(例えば、「mail.vbs」)。SMTP認証、Cc、Bcc、Reply、添付ファイルなどのうち、不要なものは消すかコメントアウトしてください。

' ************************************************************
' メールを送受信するオブジェクトの生成
' ************************************************************
Set BASP21 = CreateObject("Basp21")
Set objShell = CreateObject("WScript.Shell")

' ************************************************************
'メール送信元の設定
' ************************************************************

strFrom = "<送信元メールアドレス>"
strReply = “<返信メールアドレス>”

strServer = "<smtpサーバのアドレス>"
nPort = <smtpサーバのポート番号>
strUser = "<smtpサーバのユーザ>"
strPass = "<smtpサーバのパスワード>"

‘ SMTP AUTH用にまとめます
strMailFrom = strFrom & vbTab & strUser:strPass

' ************************************************************
'メール送信先の設定&メール本体の作成
' ************************************************************

strTo = "<送信先メールアドレス>"
strCc = "<cc先メールアドレス>"
strBcc = "<bcc先メールアドレス>"

strSubject = "<メールタイトル>"
strTextbody = "<メール本文>"

strAddAttachment = “<添付ファイルのフルパス>”

‘ メールヘッダをまとめます
strMailTo = strTo & vbTab & “cc” & vbTab & strCc & “bcc” & vbTab & strBcc & “reply-to” & vbTab & strReply

' ************************************************************
' メール送信
' ************************************************************

rc = BASP21.SendMail(strServer: nPort, strMailTo, strMailFrom, strSubject, strTextbody, strAddAttachment)

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

' メール送信結果判定
If rc = "" Then ' メール送信成功
WScript.Quit(0)
Else ' メール送信失敗
WScript.Quit(1)
End If

2.1で作成した「mail.vbs」を、コマンドプロンプトから実行します。

cscript mail.vbs

3.メールが送信されます。

今回の例では、以前掲載したWSHPowerShellだけでメールを送る場合と同じ設定項目での例ですが、WSHやPowerShellだけでメールを送る場合と比べて、BASP21のようなコンポーネントを使用すれば、リッチなメールを送信することが可能です。
また、今回の例では、WSHから呼び出して起動するものでしたが、それ以外にも様々な方法でメールを送信することができます。

2016年4月26日火曜日

JavaからAS/400 ~ カラムヘディング編

こんにちは、寺田です。



前回『JavaからAS/400 ~ メンバー編』に続き、今回は、物理ファイル(=テーブル)のカラムヘディング(フィールドの欄見出し)の取得方法についてお話します。

カラムヘディングとは、QUERYユーティリティーやデータ・ファイル・ユーティリティー(DFU)で使用されるフィールドのラベル(欄見出し)のことです。物理ファイルのフィールド定義(DDS)では、次のように COLHDGキーワードで定義します。
     A*
     A* ID    : SAMPLE01
     A* NAME  : 取引先マスター
     A*-------------------------------------------------------------
     A          R SAMPLE01R
     A*                                                             
     A            STATUS         1A         COLHDG(' 状態 ')
     A                                      TEXT(' 取引状態 ')
     A            CSTMNO         5A         COLHDG(' 取引先№ ')
     A            CSTMNM        30O         COLHDG(' 取引先名 ')
     A            CSTMNMK       30A         COLHDG(' 取引先カナ名 ')
     A            CSTMTEL       10A         TEXT(' 電話番号 ')
     A            CATNO          2A         COLHDG(' 業種№ ')
     A            SALES          8S 0       COLHDG(' 売上実績 ')
     A*
このカラムヘディング、AS/400ユーザにとってはお馴染みのようで、とあるお客様先で、物理ファイルのデータをExcelとしてダウンロードし、そのExcelの1行目に見出しとしてカラムヘディングを差し込むプログラムをVBとWSHで作りこんでいるのを見たことがあります。見出しはカラム名(上記のDDSではCSTMNOやCSTMNM)ではなくてカラムヘディングで表示するのが、AS/400ユーザでは常識のようです。

そこで、Java(JT400)でカラムヘディングを取得する方法を以下に紹介します。

1つ目は、JDBCの仕様の範囲だけで取得する方法です。
以下がそのサンプルです。
Connection con = null;
try {
    Class.forName("com.ibm.as400.access.AS400JDBCDriver");
    con = DriverManager.getConnection(
            "jdbc:as400://as400server;prompt=false", "USER", "PASSWD");
    DatabaseMetaData dmd = con.getMetaData();
    ResultSet rs = dmd.getColumns(null, "MYLIB", "MYFILE", "%");
    while(rs.next()) {
        System.out.println(rs.getString("COLUMN_NAME")
             + "," + rs.getString("REMARKS"));
    }
    rs.close();
} catch (Exception e) {
    e.printStackTrace();
}
finally {
    try {
        if (con != null) {
            con.close();
        }
    } catch(SQLException e) {
    }
}
DatabaseMetaDataクラスのgetColumns()メソッドによって、指定の物理ファイルのフィールド情報を取得します。結果がResultSetで返されてきますが、カラムヘディングはカラム名"REMARKS"に格納されています。

なお、上記のDDSのように、フィールドにCOLHDGキーワードだけでなくTEXTキーワード(テキスト記述)も定義されている場合、REMARKSにはTEXTキーワードで定義した情報が格納されます。REMARKSの情報がカラムヘディングなのか、テキスト記述なのかは判別できません。

2つ目は、毎度ですがJT400(JTOpen)のユーティリティクラスを使用する方法です。
try {
    AS400 as400 = new AS400("as400server", "USER", "PASSWD");
    as400.setGuiAvailable(false);
    as400.connectService(AS400.SIGNON);
    String path = "/QSYS.LIB/MYLIB.LIB/MYFILE.FILE";
    AS400FileRecordDescription file = new AS400FileRecordDescription(as400, path);
    RecordFormat[] format = file.retrieveRecordFormat();
    for (int i = 0; i < format[0].getNumberOfFields(); i++) {
        FieldDescription fd = format[0].getFieldDescription(i);
        System.out.println("NAME=" + fd.getFieldName());
        System.out.println("COLHDG=" + fd.getCOLHDG());
        System.out.println("TEXT=" + fd.getTEXT());
    }
}
catch (Exception e) {
    e.printStackTrace();
}
AS400FileRecordDescriptionクラスのretrieveRecordFormat()メソッドでレコード情報を取得。各フィールドのFieldDescriptionオブジェクトからカラムヘディングを取得します。この場合、カラムヘディング(COLHDG)とテキスト記述(TEXT)をそれぞれ取得するメソッドが用意されています。

3つ目は、AS/400のコマンドDSPFFD(ファイル・フィールド記述表示)を使用する方法です。この方法が、一番詳細なフィールド情報を取得することができます。

コマンドDSPFFD(ファイル・フィールド記述表示)は、その名のとおり、物理ファイルのフィールド情報を出力するコマンドです。出力されるフィールド情報には、カラムヘディングはもちろん、データタイプや長さ、さまざまな属性値なども含まれています。

例えば、次のようにコマンドを発行すると、
DSPFFD FILE(MYLIB/MYFILE) OUTPUT(*OUTFILE) OUTFILE(MYLIB/MYFILEFFD)
ファイルMYLIB/MYFILEのフィールド情報が、ファイルMYLIB/MYFILEFFDに出力されます。つまり、フィールド情報がDBのテーブルとして参照できるということです。フィールド情報のファイルを予め作成しておくか、以前のプログ『JavaからAS/400のコマンドを発行するには』で紹介したようにJT400でコマンドを発行し、あとは普通にJDBCで検索すればいい訳です。

実は、2つ目のAS400FileRecordDescriptionクラスを使う方法は、中身はDSPFFDコマンドを使った実装になっています。JT400は、JTOpenとしてソースが公開されています。そのソースを覗いてみると、いろいろと発見があって面白いですよ。


2016年4月4日月曜日

メインフレームにおけるデータストリーム概要その2~指令・副指令編

こんにちは、綱島です。




前回、データストリームの基本となるフィールドの考え方についてお話しました。
今回はは、フィールドの画面上の位置についての話をするつもりでしたが、画面を表示するためのデータストリームの指令・副指令について話をしたほうが順序としてわかりやすいので、変更しました。

フィールドの話の中に、フィールドは属性から属性までと言いました。この属性を指定するためには、副指令(オーダーとも言います)を知る必要があります。この副指令は、属性を指定したり、カーソルの位置を変えたり、文字を繰り返し表示したりするために用います。
属性を指定するオーダーは、SF(Start Field)やSFE(Start Field Extended)など複数あり、副指令の種類によってパラメータが決まっていますので、そのパラメータで色や罫線などを指定します。

では、副指令があるのなら、指令は?と思われたと思います。そうです、指令があります。
指令は、「画面を表示する」などの指令がいくつかあります。端末の画面状態をホストへ送るような指令もありますが、ホストから端末エミュレーターへ送られてくるデータのうち、画面を表示するためのデータストリームがかなりの割合を占めています。画面を表示するための指令を知っているだけで、データストリームの基礎としては十分です。簡単では?と思わないで、もう少しお付き合いください。

指令の中で、画面を表示するための指令は、2つしかありません(データストリームの種類によって、若干異なります)。
2つの指令とは、Erase/Write指令とWrite指令です(以降、単にWriteと表記し「指令」は省略します)。
Erase/Writeは、前の画面をクリアした後、副指令に従って文字などを書きます。Writeは、前の画面はそのままで、副指令に従って文字などを書きます。
違いは、最初に前の画面をクリアするか、そのままにして上書きするかの違いだけです。

データストリームは、このErase/Writeのような指令で一つのかたまりとなります。

Erase/Writeの構造について、見てみましょう。
Erase/Writeは、1バイトのWCC( Write Control Character)と複数の副指令で構成されています。なお、WCCはデータストリームの種類によって、2バイトの場合やWCCと呼ばない場合がありますが、指令の直後に指定することは変わりがありません。
Erase/Writeの構造を図示すると、図1のようになります(E/Wとは、Erase/Writeの略した書き方です)。


WCCについて、細かくは話しませんが、キー入力を許可するなどの情報が含まれています。
文字についてですが、文字は副指令の一部と考えて構いません。副指令で使用する値は、文字コードの範囲外が使用されているので、文字と副指令は区別がつきます。また、日本語は必ずシフトコードで囲まれていますので、シフトコードを副指令と考えればよいのです。
ここで、前回にも例に出しました図2の画面を例としてデータストリームはどうなるかを示します。



図3のような情報が、ホストから送られてきますので、画面の左上から複数のスペースを書き、属性を処理し、○○会社メインメニューを属性に従って書き、また複数のスペースを書き・・というように順番に画面を構成することになります。


ただ、表示したい文字列間に「複数のスペース」で場所を移動させました。最初のスペースは20個程度ですが、「○○会社メインメニュー」と「1.人事システム」の間には空行がありますので、100個以上のスペースが必要です。これでは、ただデータ量が増えるだけであまりかしこいとは言えませんし、今のような高速で通信していなかったことろは、それだけで速度が遅くなったり、通信費がかさんだりしてしまいます。
副指令は属性に関するもの以外にも、表示場所を移動させたり、同じ文字を繰り返したりできるものがあります。実際は、複数種類の副指令を使って画面を構成します。この場所を移動させる副指令が、前回少し話をしました画面の位置を指定することになります。
場所移動の副指令が入ると、図4のようになります。


また、場所を指定する副指令があると、画面の左上から順番に送らなくてもよくなるので、途中に後から挿入する場合も、後ろにつけてしまうことができます。


このようにデータストリームで画面を表示するためには、たくさんの副指令を解釈して表示します。指令は少なくても副指令が複数あり、パラメータもあるので、全体でみるとデータストリームの解釈は、そんなに簡単ではないと思っています。
次回は、主だった副指令について、話をしたいと思います。


2016年2月23日火曜日

JavaからAS/400 ~ メンバー編

こんにちは、寺田です。



前回の私からの投稿『JavaからAS/400のコマンドを発行するには』の続きです。

以前、IBM Toolbox for Javaに含まれているJDBCドライバーであるJT400を使って、AS/400上の物理ファイルのダウンロード/アップロードを行うJavaプログラムを作ったことがあります。その中で、AS/400特有の仕様からいろいろと問題に遭遇し、調査に時間を要しました。今回は、そのいくつかを紹介したいと思います。

まずは、「メンバー」についてです。

前回、「AS/400の物理ファイルとは、その実体はDB2のテーブルです。」と言いました。なので、JDBCで以下のようにSQLを発行することで、物理ファイルの中身を取得することができます。
SELECT * FROM ライブラリ名.ファイル名

物理ファイルは、実際に(物理的に)はデータ・レコードを収容しているデータベース・ファイルです。データ・レコードは物理ファイル・メンバーにまとめられ、各メンバーにはそのデータに対する独自のアクセス・パスがあります。通常、物理ファイルは1つのメンバーからなるので、上記SQLのように「ライブラリ名.ファイル名」で指定ができます。

しかし、物理ファイル内に複数のメンバーを持たせることもできるので、そのとき、SQLでどうやってメンバーを指定すればいいのか?例えば、
SELECT * FROM ライブラリ名.ファイル名(メンバー名)
とすると、当然ながら構文エラーとなります。

いろいろ調べてみた結果、別名(ALIAS)を作成すれば良いということが分かりました。
事前に以下のような「CREATE ALIAS」ステートメントでALIASを作成しておきます。
CREATE ALIAS MYLIB.MYALIAS FOR MYLIB.MYFILE (MBR)

そうすることで、SQLでの検索が可能になります。
SELECT * FROM MYLIB.MYALIAS

終わったら、「DROP ALIAS」で削除しておきます。
DROP ALIAS MYLIB.MYALIAS


もうひとつ、メンバーの話のついでに、「メンバーの一覧を取得」する方法を紹介します。

物理ファイル(テーブル)の一覧の取得はJDBCで可能なのですが、JDBCに「メンバー」という概念はないので一覧を取得することはできません。

そこで、JT400(JTOpen)のユーティリティクラスの登場です。前回も言いましたが、JT400(JTOpen)にはJDBCの実装だけではなく、JavaからAS/400のさまざまなリソースにアクセスするためのユーティリティクラスが含まれています。そのユーティリティクラスを使ってメンバー一覧を取得するサンプルが、以下になります。

AS400 as400 = new AS400("172.22.1.10", "USERID", "PASSWD");
as400.setGuiAvailable(false);
as400.connectService(AS400.SIGNON);

MemberList members = new MemberList(as400, "MYLIB", "MYFILE");
members.load();
MemberDescription[] descs = members.getMemberDescriptions();
for (int i = 0; i < descs.length; i++) {
    String val = (String)descs[i].getValue(MemberDescription.MEMBER_NAME);
    System.out.println("member name=" + val);
}

まさにMemberListというクラスがあり、MemberDescriptionの配列が取得できます。MemberDescriptionには、メンバー名や属性などの情報が含まれています。

このように、メンバーに限らず、物理ファイルやライブラリの一覧や情報を取得することができるので、JT400、なかなか便利です。

次回もJT400を使ったお話をしようと思います。


2016年1月26日火曜日

Hyper-V をコマンドラインから起動/サスペンド/シャットダウンする

こんにちは。近藤です。




前回の担当回では、Windowsでよく利用されるパーソナル向け仮想環境であるVMWare Workstation Playerを、コマンドラインから起動/サスペンド/シャットダウンする方法を記載しました。
今回は、もう1つのWindowsでよく利用されるパーソナル向け仮想環境であるHyper-Vを、コマンドラインから起動/サスペンド/シャットダウンする方法を記載します。
今回は、Windows10を例にして説明します。

参考:Windows10の仮想環境を有効化

Windows10は、デフォルトでは仮想環境が有効になっていません。
有効にするには、[コントロールパネル]-[プログラム]-[プログラムと機能]-[Windows機能の有効化または無効化]にある「Hyper-V」にチェックを入れます。
(CPUが未対応である場合など、Hyper-Vの稼働環境を満たしていない場合は、チェックすることができません)




コマンド

Windows7以前のクライアントPC向けに用意されていた仮想環境であるVirtual PCでは、コマンドから仮想マシンの起動/終了などを実行するにはかなり面倒なスクリプトを書く必要がありましたが、Windows8以降+PowerShell3.0の環境では、下記のコマンドだけで実行できるようになりました。

起動(PowerShell)

仮想マシンの起動を行います。
Start-VM -Name "<起動する仮想マシン名>"

一時停止(PowerShell)

起動している仮想マシンをサスペンドします。
Suspend-VM –Name "<サスペンドする仮想マシン名>"

再開(PowerShell)

サスペンドしている仮想マシンを再開します。
Resume-VM –Name "<再開する仮想マシン名>"

シャットダウン(PowerShell)

起動している仮想マシンをシャットダウンします。
Stop-VM -Name "<シャットダウンする仮想マシン名>"

コマンドプロンプトやバッチから起動する場合は、管理者権限がある状態で、下記コマンドの先頭に「powershell」を付与して、powershellで起動します。

<例>
powershell Start-VM -Name "<起動する仮想マシン名>"

このような感じで、GUI画面を経由せずに、コマンドから簡単に操作することができます。
既存のバッチと組み合わせるなどして、使ってみてください。