PowerBuilderのソースファイル(.SRDファイル)からSQLを抽出するための正規表現です。

試した範囲ではデータソースとして設定されているSQL、PBSELECT(PowerBuilder独自のSQL)ともに抽出できています。
SQLの場合は、複数行にわたるSQLやダブルクォートで囲まれていても抽出ができることを確認しています。

retrieve=(\”[\s\S]*?^(\~\”)?\”|\”\s{0,}PBSELECT.*\”)

retrieve=(\”[\s\S]*?(^(\~\”)?|[\s\w;])\”|\”\s{0,}(?!PBSELECT\s{0,})[\s\S]*?\”|\”\s{0,}PBSELECT.*\”)

※2019/01/22 12:30 抽出できないケースがあることが判明したので、正規表現を修正しました。

PowerBuilderライブラリファイル(.PBLファイル)から.SRD形式のソースファイルの作り方については、『PowerBuilderのソースファイルをテキスト形式で一括エクスポートするツール』をご覧ください。

pbl_exporttool

PowerBuilderのソースファイル(ライブラリ/PBLファイル)は、独自形式のためPowerBuilder IDE上でしか開くことができません。
しかし、PowerBuilderが提供する組み込み関数の中には、ソースファイルの内容を解析し登録されているオブジェクトの一覧を取得したり、本体部分をテキストとして取得したりする機能が含まれているので、中身を取り出しテキスト化すること自体は可能そうです。

今回は、この機能を使ってPBL形式のソースファイルをテキスト形式のソースファイルとして一括エクスポートするツールを作成しました。

Read More

Windows 10上にVB6の開発環境を構築する必要があり作業を行ったのですが、そのときいろいろな問題が発生しました。
インターネット上には、Windows 10へVB6をインストールための様々な情報が公開されていますが、実際に試してみると公開されている情報と違う箇所や端折れる手順などがありました。
今回、実際に行った一連の作業を記事にまとめました。

確認を行った環境

  • Windows 10 Pro Version 1803 (64ビット版)
  • Visual Basic 6.0 Enterprise Edition
    Visual Studioサブスクリプション(https://docs.microsoft.com/ja-jp/visualstudio/subscriptions/ )で提供されているもの

作業の流れ

  • VB6本体のセットアップ
  • VB6サービスパック(SP6)の適用
  • VB6SP6 累積的な更新プログラムの適用
  • VB6の起動とプロジェクトの読み込み

※注意
Visual Basic 6.0は、開発元のMicrosoftのサポートが終了した開発環境です。
最悪の場合、システムやデータに復旧不可能なダメージを与える可能性があります。
実際の導入にあたっては細心の注意を払い、ご自身の責任においてお試し下さい。


Read More

ゲームボーイミクロはとても小さくガジェット好きの心をつかんで離さないゲーム機ですが、ゲームボーイアドバンスSPやDS/3DSシリーズと違い、液晶画面がむき出しの状態なので画面に傷がつかないか常にひやひやします。

もともとは専用の布ポーチが付属しており、持ち運びや保管はポーチに入れて画面を保護するようになっていたのですが、今となっては入手が困難。
じゃあ代わりのものを…と探してみても、ミクロがぴったり収まるサイズのケースというのがなかなか見つからないんですよね。

なかば諦めかけていたのですが…

ついに見つけました!

100円ショップ『ザ・ダイソー』で買い物をしているとき、スマホのアクセサリーを扱うコーナーで「イヤホンケース」なるものを発見。
見た瞬間、その大きさにピーンときました。

ダイソーのイヤホンケース

早速買い求めてミクロを収納してみたところ、「ミクロ用に作ったのではないか!?」と思うくらいピッタリ!
ちょっとピッタリすぎるかなという感じも若干しますが、傷が付いたり塗装が剥げたりすることはなさそうです。

そこそこの強度がありそうな素材で作られているので、カバンの中で”つぶれ”や”こすれ”には強そうです。
試す勇気はありませんが、落下もある程度までは耐えてくれそうな感じがします。

ダイソーのイヤホンケースにミクロを収納した状態

網ポケットの部分にイヤフォンを収納した状態でもきちんとファスナーがしまりました。

IMG_9221

商品名は『イヤホンケース&小物入れ(角形)』、型番は”K-18P-12”、”002”のようです。
色は3色くらいありました。
価格は税別100円です。


Windows 10のWSL向けに最適化されたという触れ込みの新しいLinuxディストリビューション『WLinux』がWindowsストアで公開されました。

さっそく購入してみたのですが、起動した瞬間、いきなりのエラー。
「WslRegisterDistribution failed with error: 0x80070003」と表示され、表示されたメッセージに従いキーを押すと終了してしまいました。
萎えます。

2018-10-02

この現象を回避する方法が分かったので、記述します。

Windowsの設定を開き(Windowsキー + “i”の同時押しが便利です)、[システム]-[ストレージ]-[新しいコンテンツの保存先を変更する]画面で表示される、[新しいアプリの保存先]の設定値を確認してください。

この設定値がCドライブ以外に設定されていると「WslRegisterDistribution failed with error: 0x80070003」と表示されてしまうようです。

「Cドライブ」に変更した後、適用ボタンを押して設定を反映します。

「新しいアプリの保存先」に「Cドライブ」以外を設定した状態でWLinuxをインストールしている場合、いったんWLinuxをアンインストールします。
アンインストールした後、WLinuxを再度インストールを行い起動すると先ほどのようにエラーが表示されず次のフェーズへと進めるようです。

2018-10-02 (1)

お客様から「Excelのメニュー項目の表示が英語になってしまった」と問い合わせをいただきました。

最初は、Excelの設定画面([ファイル]-[オプション]-[言語])で「表示言語の選択」の設定が変わってしまい英語表記になってしまったのかと思ったのですが、現地で調査をしてみるとどうも勝手が違うようです。

ここまでにわかっていること

  • Excelの表記が英語表記になっていた
  • WordやPowerPointは日本語表記のまま
  • Excelの設定は変えていない

マイクロソフトのコミュニティを調べてみると同じような現象の報告がありました。「Excel2016の英語設定を日本語に変更する方法をお教えください。(サーフェスラップトップ)

ここに書かれているようにWindowsの表示言語の設定(設定の[時刻と言語]-[地域と言語]-[言語])などを確認しましたが、Windowsの設定は「日本語」で問題がありません。
Windows Updateもすべて正常に行われているようです。
ダメもとでWindowsに言語を追加してみたり、Windowsの表示言語をいったん日本語以外の言語に切り替えて、日本語に戻してみたりしましたがExcelの表記は英語のままです。

追加でわかったこと

  • Windowsの表示言語の設定は「日本語」
  • Windows Updateはすべて正常に行われている

もう一度マイクロソフトのコミュニティに投稿された情報をよく読むと重要な情報を見つけました。

しかし、ストアアプリ版Officeなので、Windowsの表示言語と連動していて、画像のように、言語を追加できないようになっています。

問題を起こしたパソコンのExcelの設定画面を確認してみると、表示言語を切り替えるための項目が表示されていないことがわかりました。
インストールされているものはストアアプリ版のOfficeのようです。

ちなみに、デスクトップ版Excel 2016の設定画面は下記のような表示になります。
「表示言語の選択」という項目で表示言語とヘルプ言語の設定や、追加の言語リソースの取得(言語パック)ができるようになっています。

スクリーンショット 2018-06-26 0.41.44

さらに、確認をするとネットワークの接続が不安定だったようでインターネットにうまく接続できない状態があったようです。

さらに追加でわかったこと

  • インストールされているOfficeはストアアプリ版
  • ネットワーク接続が不安定だった

Windowsの『ストア』で「ダウンロードと更新」の状況を確認すると、Office系のアプリがダウンロードの途中でエラーになって保留状態になっていました。

保留状態になっているものを手動で更新し、更新が完了したところでExcelを立ち上げてみると…

日本語表記が復活!!

ストアアプリの更新に失敗したのが原因のようです。


パソコンのメーカーや導入した時期なども関係していた

今回の問題が起きたパソコンはデル社製のデスクトップマシンで2018年3月に導入したパソコンだったのですが、ここに落とし穴がありました。

デルのWebサイトで公開されているナレッジベース情報に「Office 2016 プリインストール版 アクティベーション方法(Windows 10)」という項目があります。

ここに以下に引用する記載があります。

    • Windows 10 Fall Creators Update 以降が搭載された PC にプレインストールされた Office 2016 は、Windows 10 ストアアプリ版 Office 2016 がプレインストールされています。
    • Office 2016 の再インストールは、Windows 10 の “Microsoft Store” アプリからインストールします。
    • 再インストールには、インターネット接続と初回セットアップで使用した Microsoft アカウントが必要となります。

導入した時期が2018年3月なので、Fall Creators Updateが適用されたWindows 10 が導入されています。
Fall Creators Updateが適用されたパソコンのプレインストール(PIPC) Office 2016なのでストアアプリ版Officeが導入されていたようです。

ストアアプリ版のOfficeなんてSurfaceだけかと思ったら、ほかのメーカーのパソコンにも入っていたとは…
今回はじめて知りました。


結論

Excelの表記が英語表記になった場合、導入されているOfficeがストアアプリ版かデスクトップ版かをチェックする。
ストアアプリ版の場合、『ストア』の「ダウンロードと更新」の状況を確認し、失敗している場合、ダウンロードと更新のリトライを行う。

IMG_7231

PORTABOOKにWindows 10 April 2018 Update(バージョン 1803、ビルド番号 17134)をインストールしました。

ストレージが32GBと非常に少ないPORTABOOKなのでオンラインでアップデートというわけにはいきませんが、USBメモリを2本用意し一本をインストールメディアもう一本をテンポラリとするいつもの方法でアップデートすることができました。
(PORTABOOK(XMC10)にWindows 10 Creators Update(Ver. 1703)を入れる方法 を参照)


SmartGWTのフォーム上で任意スケールの数値入力を行うためのコンポーネントが用意されていなかったので作成しました。

このコンポーネントは、SmartGWTのcom.smartgwt.client.widgets.form.fields.TextItemクラスを拡張して実装しています。

setLengthメソッドで全体の桁数を設定します。
桁数には、入力された文字数そのもので評価され、符号や小数点などもカウントされるので注意が必要です。

setDecimalPadメソッドで小数点以下の桁数を設定します。

getValueメソッド、またはgetValueAsBigDecimalメソッドで入力された結果をBigDecimal型で取得します。
BigDecimal型への変換は、setDecimalPadメソッドで指定された小数点以下の桁数、setRoundingModeメソッドで指定された丸め方法で変換されます。
入力されたテキストが数値としてパースできなかった場合は、nullが返ります。

動作確認を行った環境:

Java

Java SE Development Kit 7

SmartGWT

6.1 PRO

ライセンス

NYSL

ダウンロード

BigDecimalItem.java.zip

// This software is distributed under the license of NYSL.
// ( http://www.kmonos.net/nysl/ )
package com.ria_lab.gwt.smartgwt.client.ui.form;

import java.math.BigDecimal;
import java.math.RoundingMode;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.i18n.client.NumberFormat;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.FormItemValueFormatter;
import com.smartgwt.client.widgets.form.FormItemValueParser;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.form.fields.TextItem;

/**
 *	SmartGWTの com.smartgwt.client.widgets.form.DynamicForm で
 *	数値型(java.math.BigDecimal)を入力するためのコンポーネント
 */

public class BigDecimalItem extends TextItem {

	/** */
	private Integer scale;
	
	/** */
	private RoundingMode roundingMode = RoundingMode.DOWN;
	
	/** */
	private NumberFormat format;
	
	/** */
	private FormItemValueFormatter formatter =
			new FormItemValueFormatter() {
			
			@Override
			public String formatValue(Object value, Record record, DynamicForm form, FormItem item) {
				
				if (value == null) {
					return "";
				}
				
				try {
					return asBigDecimal(value.toString(), scale, roundingMode).toString();
				} catch (NumberFormatException e) {
					return value.toString();
				}
			}
		}; 
	
	/** */
	private FormItemValueParser parser = 
			new FormItemValueParser() {
				
				@Override
				public Object parseValue(String value, DynamicForm form, FormItem item) {
					
					if (value == null || value.trim().isEmpty()) {
						return null;
					}
					
					try {
						BigDecimal decimal = asBigDecimal(value.toString(), scale, roundingMode);
						return format == null ? decimal : format.format(decimal);
					} catch (NumberFormatException e) {
						return value;
					}
				}
			};

	/**
	 *	Constructor
	 *	
	 */
	public BigDecimalItem() {
		super();
		init();
	}

	/**
	 *	Constructor
	 *	
	 *	@param jsObj
	 */
	public BigDecimalItem(JavaScriptObject jsObj) {
		super(jsObj);
		init();
	}

	/**
	 *	Constructor
	 *	
	 *	@param name
	 */
	public BigDecimalItem(String name) {
		super(name);
		init();
	}

	/**
	 *	Constructor
	 *	
	 *	@param name
	 *	@param title
	 */
	public BigDecimalItem(String name, String title) {
		super(name, title);
		init();
	}
	
	/**
	 *	
	 */
	private void init() {
		
		setEditorValueFormatter(formatter);
		setValueFormatter(formatter);
		setEditorValueParser(parser);
		setKeyPressFilter("[0-9\\-\\+\\.]");
	}
	
	/**
	 *	@see com.smartgwt.client.widgets.form.fields.FormItem#setDecimalPad(java.lang.Integer)
	 */
	@Override
	public void setDecimalPad(Integer decimalPad) {
		
		if (decimalPad != null && decimalPad < 0) {
			throw new IllegalArgumentException();
		}
		
		super.setDecimalPrecision(decimalPad);
		scale = decimalPad;
		format = getNumberFormat(decimalPad);
	}
	
	/**
	 *	@return roundingMode
	 */
	public RoundingMode getRoundingMode() {
		return roundingMode;
	}

	/**
	 *	@param roundingMode roundingMode
	 */
	public void setRoundingMode(RoundingMode roundingMode) {
		
		if (roundingMode == null) {
			throw new IllegalArgumentException();
		}
		
		this.roundingMode = roundingMode;
	}

	/**
	 *	@see com.smartgwt.client.widgets.form.fields.FormItem#getValue()
	 */
	@Override
	public Object getValue() {
		return getValueAsBigDecimal();
	}
	
	/**
	 *	
	 *	@return
	 */
	public BigDecimal getValueAsBigDecimal() {
		
		String s = getValueAsString();
		if (s == null || s.trim().isEmpty()) {
			return null;
		}
		
		try {
			return asBigDecimal(s, scale, roundingMode);
		} catch (NumberFormatException e) {
			return null;
		}
	}
	
	/**
	 *	
	 *	@param s
	 *	@param scale
	 *	@param roundingMode
	 *	@return
	 */
	private static BigDecimal asBigDecimal(String s, Integer scale, RoundingMode roundingMode) {
		return scale == null ? new BigDecimal(s) : new BigDecimal(s).setScale(scale, roundingMode);
	}
	
	/**
	 *	
	 *	@param scale
	 *	@return
	 */
	private static NumberFormat getNumberFormat(Integer scale) {
		
		if (scale == null) {
			return NumberFormat.getFormat("0");
		}
		
		StringBuffer sb = new StringBuffer(scale == 0 ? "#0" : "#0.");
		for (int i = 0; i < scale; i++) {
			sb.append("0");
		}
		return NumberFormat.getFormat(sb.toString());
	}
}

IMG_5697

PORTABOOKにWindows 10 Fall Creators Update(バージョン1709、ビルド番号16299)をインストールしてみました。

基本的な流れは、Windows 10 Creators Update(バージョン1703、ビルド番号15063)の時と同じく、USBメモリを2つ用意して、ひとつをインストールメディア、もうひとつをテンポラリとしてインストールを進めます。

Windows 10 Creators Updateのときはインストールメディアとして使うUSBメモリの容量が4GB以上だったのに対し、Windows 10 Fall Creators Updateでは8GB以上のUSBメモリが必要になっているので注意が必要です。

2017-10-23 (14)

具体的な手順については、過去の記事を参照してください。

PORTABOOK(XMC10)にWindows 10 Creators Update(Ver. 1703)を入れる方法

インストールメディア作成の開始からWindowsの起動ができるまでの所要時間は、だいたい4時間弱でした。

Windows 10 Fall Creators Updateのインストール前に、本体ストレージにインストールしたソフトをいったん削除し、9.3GB程度の空き領域を確保した状態でインストール作業を始めました。
Windows 10 Fall Creators Updateインストール直後の空き容量は、4.7GB程度です。

MicrosoftのDBサーバ『SQL Server』に、Microsoft純正のJDBCドライバを用いてJavaから接続した際のハマりメモ。

下記のようなメッセージが表示された人向けです。

  • ERROR-CODE: 0 / SQL-STATE: 08S01

    ホスト 192.168.1.XXX、ポート 55378 への TCP/IP 接続が失敗しました。エラー: “接続のタイムアウト: 詳細情報なし。接続プロパティを調べて、SQL Server のインスタンスがホスト上で実行されていて、ポートへの TCP/IP 接続が許可されており、そのポートへの TCP 接続がファイアウォールにブロックされていないことを確認してください。”。

  • ERROR-CODE: 18456 / SQL-STATE: S0001

    ユーザーユーザ名はログインできませんでした。 ClientConnectionId:XXXXXXXXXX-XXXX-XXXXXXXXX

とりあえずの結論は、「SQL Serverの『名前付きインスタンス』と『TCP動的ポート』、ファイアウォールの設定を確認する」です。

きちんと検証はしていませんが、Accessにリンクテーブルを作ろうとした際、ODBCでも同様の現象が発生しました。
この記事に記載した内容を確認・設定しJDBC接続できるようにしたあとで、ODBC接続を試みたら難なく接続することができました。ODBC経由でSQL Serverに接続できない問題が起きているかたも、この記事の内容が役に立つと思います。


対処

  • SQL Server Browserは起動しているか?

コントロールパネルの『サービス』から確認する。
起動していない場合は、SQL Server Browserサービスを起動する。
(その他、SQL Server関連のサービスも起動されていることを確認する。これを忘れて少しハマりました。)

詳細は、Microsoftのサイトの『SQL Server Browserサービス』を参照。

  • SQL Serverが稼働しているマシンのポート開放の確認

SQL Serverへの接続に必要なポートが開放されているか、(主にSQL Serverが稼働しているリモートマシンの)ファイアウォールなどの設定を確認する。
JDBCの接続URLの記法により、必要な開放ポートが変わるので注意。

	// この部分
	Connection con = DriverManager.getConnection("jdbc:sqlserver://192.168.1.XXX:55378;instanceName=SQLEXPRESS;databaseName=データベース名", "ユーザ名", "パスワード";
“jdbc:sqlserver://192.168.1.XXX\\インスタンス名;databaseName=データベース名”の場合

ポート番号 1434とインスタンスがリッスンしているポート番号が開放されているか確認

“jdbc:sqlserver://192.168.1.XXX;instanceName=インスタンス名;databaseName=データベース名”の場合

ポート番号 1434とインスタンスがリッスンしているポート番号が開放されているか確認

“jdbc:sqlserver://192.168.1.XXX:インスタンスがリッスンしているポート番号;instanceName=インスタンス名;databaseName=データベース名”

インスタンスがリッスンしているポート番号が開放されているか確認

URL記法の詳細は『接続URLの構築』、開放ポートの詳細は『インターネットを介しての SQL Server への接続』を参照

URLの中にユーザ名やパスワードを持たせた場合、java.sql.DriverManager#getConnection(String url)も使える。

PostgreSQLなどをJDBCを介して使っていると、つい接続URLに”jdbc:sqlserver://192.168.1.XXX:インスタンスがリッスンしているポート番号\\インスタンス名;databaseName=データベース名”みたいな書き方をしてしまいますが、これが受け付けてもらえず例外が発生しLocalizedMessageプロパティには「ポート番号 1433\SQLEXPRESS は無効です。」というようなメッセージが設定されます。(ErrorCodeプロパティには0、SqlStateプロパティにはnullが設定されていました)

  • インスタンスがリッスンしているポートの確認

SQL Server構成マネージャーを起動し、『SQL Serverネットワークの構成』からSQL Serverのインスタンスを選択し、一覧表示されたプロトコルから『TCP/IP』を選択。
プロパティを表示し、『IP All』の『TCP動的ポート』に設定されている値を確認する。

SQL Server構成マネージャーは、スタートメニューの検索ボックスで「sqlservermanager12.msc」とか「sqlservermanager13.msc」とか打ち込むと表示される。
されない場合は、\Windows\SysWOW64のフォルダあたりを探す。

そもそもSQL Serverがリモート接続可能な状態で動いているか、TCP/IPで接続可能になっているかなども確認が必要です。

詳細は『構成マネージャー』を参照

2017-08-17 (2)

確認に用いたプログラム

Windows 10上で稼働しているSQL Server 2014 Expressに、リモートのMacから接続して検証。
Mac側のJava環境はJava SE 7(1.7.0_51)、JDBCドライバは『Microsoft JDBC Driver 6.0 for SQL Server』のJDBC 4.1版を使用。

// This software is distributed under the license of NYSL.
// ( http://www.kmonos.net/nysl/ )

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

import com.microsoft.sqlserver.jdbc.SQLServerException;

public class Test {

	public static void main(String[] args) {

		// 名前付きインスタンス"SQLEXPRESS"上のデータベースに接続する際のJDBCの接続URL

		// ポート1434とTCP動的ポートの開放が必要
		String url = "jdbc:sqlserver://192.168.1.XXX\\SQLEXPRESS;databaseName=データベース名";

		// ポート1434とTCP動的ポートの開放が必要
		// String url = "jdbc:sqlserver://192.168.1.XXX;instanceName=SQLEXPRESS;databaseName=データベース名";

		// TCP動的ポートの開放が必要
		// String url = "jdbc:sqlserver://192.168.1.XXX:55378;instanceName=SQLEXPRESS;databaseName=データベース名";

		// SQL Serverのユーザ名とパスワード
		String username = "ユーザ名";
		String password = "パスワード";

		try {
			// JDBCドライバをロード
			Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
			// SQL Serverに接続
			Connection con = DriverManager.getConnection(url, username, password);

			// SQL Serverに問い合わせ
			Statement stmt = con.createStatement();
			ResultSet rs = stmt.executeQuery("select * from 適当なテーブル");
			while (rs.next()) {
				System.out.println(rs.getString("テーブルの適当な項目"));
			}

			// 後処理
			rs.close();
			stmt.close();
			con.close();

		} catch (SQLServerException e) {
			// SQL Server固有の例外
			System.out.println("ERROR-CODE:\t" + e.getErrorCode());
			System.out.println("SQL-STATE:\t" + e.getSQLState());
			System.out.println("MESSAGE:\t" + e.getLocalizedMessage());
			e.printStackTrace();
		} catch (Exception e) {
			// その他の例外
			e.printStackTrace();
		}
	}
}