ラベル Delphi の投稿を表示しています。 すべての投稿を表示
ラベル Delphi の投稿を表示しています。 すべての投稿を表示

2017年5月8日月曜日

SAS Log Utility 1.9.1.3

不具合修正中です。潜在的なバグのパターンを定義する機能に不具合あるので直します。あと、SAS9.4TS1M4に合わせて、キーワードを修正しないといけない。

2017年3月7日火曜日

SAS Log Utility 1.9.1.2

Vectorに新しいバージョンの公開を依頼しました。今回の修正内容は以下のとおりです。

  • EXPORTの機能制限を解除
  • 有効期限を2019年12月末に設定



使おうと思ったら有効期限切れていて、弱りました。エクスポートの制限解除するのが面倒なのでロジックをコメントアウトしました。これを使って、あるSASプログラムの構造を解き明かそうと下準備進めています。解析するプログラムはAPM、SASの監査のデータを作る仕組みです。

2016年11月28日月曜日

Excel Page Setupの修正案

機能追加を検討しています。

  • セルの値が値か数式かによってフォントの色を変更する
  • 中味がない空のシートを削除する
  • 行の高さを調整する
  • シート全体のフォントを設定する
これは最近読んだ本の中に書かれていたことです。実装して良いのか?

2016年2月21日日曜日

SAS Log Utility 1.8.1.1, ログファイルのエンコーディングを判定

Vectorに新しいバージョンの公開を依頼しました。今回の修正内容は以下のとおりです。

  • 不具合の修正
  • SASログファイルのエンコーディングを自動判定
  • SJIS, JIS, EUC, UTF8N, UTF8, UTF7など複数のエンコーディングに対応
  • Optionsのメニューの構成を変更
  • 日本語のマッチングパターン(keyword.ini)を訂正



ログファイルのエンコーディング判定は、ココの情報が役立ちました。これが無ければ、短時間で実装できなかったです。

ListViewのソートは、DEBUGのシンボルを定義したときと、外したときで動作が異なっていました。原因分からず。機能的には、だいぶ落ち着いてきたと思います。そろそろメジャーバージョンを上げて、処理構造の無駄を取り除きたいです。

2016年2月17日水曜日

EncodeDetect.pas

開発のメモです。
ログファイルのエンコーディング判定の関数、下にネタがあります。

EncodeDetect : EncodeDetectリファレンス

http://www.watercolor-city.net/ct_delphi/delphi_tiburon/doc_thirdparty/tp_ed_ref.htm

これを使ってコードを判定、TEncodeingを生成した後します。
StringListからEncodingを指定して、読み取ると正しく読み取れました。
試しにElapsed Timeの表示に組み込んだらあっさりと動きました。

2016年2月15日月曜日

UTF-8のログ

読み込めないSASログがあった。調べてみたらUTF-8だった。特に機能仕様には明記していなかったが、扱えるのはANSI, SJISのファイルです。

UTF-8はBOMあり、BOMなしで扱いが異なる。
別途サンプルのProjectを作って、検証から始める。

仕方ないので、メモ帳でSJISに変換してしのぎます。

実装の参考記事は こちら です。

2016年2月14日日曜日

SAS Log Utilityの概要

2009年に書いたツールの概要を加筆します。
SAS Log Utilityの概要について説明します。

概要
SAS Log Utilityは、SASプログラムが出力するログファイルを分析して、パフォーマンス診断や入出力の解析に役立つ情報を作成します。SAS Log Utilityを使うと以下のことができます。
  • SASプログラムの処理時間をDATAステップで集計して、ボトルネックとなっている処理を見つけることができます。
  • SASプログラムがどのようなデータを読み書きしているか、DATAステップ又はプロシージャ単位で捉えて、データの流れを理解することができます。
  • MPRINTのログを捉えて、マクロ単位の処理時間を集計します。
  • 複数のSASプログラムがどのようなデータを読み書きし、プログラム間でのデータの連携を可視化します。
機能
  • SASログからDATAステップ/プロシージャ単位の処理時間を抽出
  • SASログから処理時間を抽出し、データセット単位で処理に要した時間を集計
  • SASログからDATAステップ/プロシージャの入出力を抽出し、データの生成、読み取り、更新、削除の流れを表形式に出力
  • 設定ファイルの切り替えで、日本語と英語のSASログに対応
  • エラーにつながるNOTE:のメッセージをSASログから捕捉
  • INIファイルを追加、修正して日本語、英語以外のSASログを解析可能
  • SASログからMPRINTのログを抽出し、マクロ単位の処理時間を集計
  • SASログの分析結果をExcelに出力

SAS Log Utility 1.7.1.16, 不具合修正と設定ファイルの切り替え機能を追加

Vectorに新しいバージョンの公開を依頼しました。今回の修正内容は以下のとおりです。

  • 不具合の修正
  • 日本語と英語の設定ファイルを分けて、nlsのサブフォルダ下に移動
  • システムのデフォルトの言語から、設定ファイルを切り替えるように修正
  • Optionsのメニューの構成を変更

今回、日本語、英語の設定を分けたのが大きな変更点です。仕組みとしてはnlsフォルダの下に、ISO言語省略名のサブフォルダを定義して、INIファイルを作成すれば、他の言語も追加できます。が、まだ検証できていません。

修正した不具合は以下のものです。

  • FILENAMEを使わないで直接ファイルのパスを指定しているときに、入出力を捕捉できない
  • データセット名の変更が正しくCRUD表に反映されない
  • 英語のSASログで、データセットの書き込み(W)が正しく反映されない

他の言語の対応は、時間のあるときに試したいです。
開発で謎なのが、Patterns... のボタンにアイコンを表示していたのですが、いつのまにか表示されなくなりました。IDEの中だと、鉛筆のマークが出ているのですが、実行すると消えてしまいます。この検証はまた時間のあるときに行います。

2016年2月13日土曜日

Delphi 条件付コンパイルの設定

開発のメモです。
リリース、デバッグ版とは別にインターナルのバージョンを作りました。条件付コンパイルの設定が分からなかったので、設定画面を貼り付けておきます。Vectorに載せるリリース版から分岐して、仕事で使うためのバージョンを作成しました。


土曜日の作業で、英語版の設定ファイルが8割がたできました。
明日、まとめてVectorに新しいバージョンを載せたいです。



2016年2月9日火曜日

NLS下のフォルダを探して、メニューを設定する(2)

開発のメモです。
設定ボタンの配置を換えました。
設定ボタンに16x16のアイコンを設定しました。
ISO言語省略名の選択は、ラジオボタンのタイプに変更しました。
潜在的なバグを見つけ出すパターンの設定は、Potential Problemのタブの下に移動しました。
言語の設定を切り替えるたびに、設定ファイルを読み直すように実装しました。





今日は、有給休暇でした。
銀行の手続きで3時間も掛かりました。

2016年2月7日日曜日

NLS下のフォルダを探して、メニューを設定する

開発のメモ。SASに倣って、NLSのフォルダ下にある言語のサブフォルダを見て、設定を切り替えられるように作成中です。



2016年2月1日月曜日

SAS Log Utility, 多言語対応の仕組みを考える

多言語対応で必要なものは何?

設定ファイルは、ISO言語省略名ごとに保持できるようにしたい。

どこに、設定ファイルを保持するか?
!SASROOT\nls\ja の形に倣って設定ファイルを配置するか?
それとも、設定ファイルの後ろにISO言語省略名を付与するのか?

LOCALEの取得は、Windows.GetLocaleInfoでできる。

言語の切り替えは、メニューから行う。
切り替えはツールの再起動なしで、反映できるようにしたい。

言語を切り替えて、ダイアログの表示を切り替えられるか?
reinit.ReinitializeFormsは使えるのか?
reinit.LoadNewResourceModuleは使えるのか?

他に使い出のあるものは何?

マイグレーション案件、面倒なことが色々ある。
何か効率化できるネタはないか。
VAの構成って面倒、設定だけではなくエビデンスの取得もできる何かが欲しい。

移行で毎回手を焼くのが、過去データの移送と変換です。
量が多いので、並列化したり、夜間に差分検出して移送する、中断、再開の制御を入れています。

他には?
BI Serverの構成が面倒です。
SMCの管理は苦手なのです、私はね。



2016年1月30日土曜日

SAS Log Utility 1.6.1.8, 不具合修正

Vectorに登録の申請をしました。
修正したのは以下の点です。

  • NOTE:でチェックするパターンを追加
  • ステータスバーにISO言語省略名を表示
  • ログの行末に追加されている空白又はタブを削除して処理
  • ListViewのソートの不具合を修正

ステータスバーに言語省略名を表示したのは、多言語対応の準備です。
行末のタブ又は空白を削除するようにしたのは、SASログをEXCELファイルに貼って渡す人がいて、処理の区切りを正確に判定できなかったためです。これがメモリリークの原因のひとつになっていました。ちなみに、EXCELに貼り付けて渡すとダブルクォートがエスケープされて、正しくパースできないことがありますので、私はWinZipで圧縮して渡します。

ステータスバーの左に言語省略名追加


記録まで

2016年1月27日水曜日

やること

ログを検査するパターン追加

NOTE: CASE式にELSE句がありません。すべてのWHEN句の条件に合わなかった場合、CASE式の結果は欠損値になります。

APPENDのパターン対応
NOTE: WORK.ABCをWORK.DEFに追加します。
NOTE: データセットWORK.ABCから0オブザベーションを読み込みました。
NOTE: 0オブザベーションが追加されました。
NOTE: データセットWORK.DEFは0オブザベーション、20変数です。
NOTE: PROCEDURE APPEND処理(合計処理時間):
      処理時間           0.00 秒
      CPU時間            0.01 秒

NOTE: Appending WORK.ONE to WORK.BASE.
WARNING: Variable c was not found on BASE file. The variable will not be added to the BASE file.
WARNING: Variable a has different lengths on BASE and DATA files (BASE 3 DATA 4).
WARNING: Variable b has different lengths on BASE and DATA files (BASE 5 DATA 4).
WARNING: Variable d was not found on DATA file.
NOTE: FORCE is specified, so dropping/truncating will occur.
NOTE: There were 4 observations read from the data set WORK.ONE.
NOTE: 4 observations added.
NOTE: The data set WORK.BASE has 4 observations and 4 variables.
NOTE: PROCEDURE APPEND used (Total process time):
      real time           0.15 seconds
      cpu time            0.06 seconds

2016年1月17日日曜日

Windows.GetLocaleInfoでLanguage Tagを取得

ツールのI18Nの検討メモです。
設定ファイルの言語を区別するため、Language Tag(ja, JP, en-usとか)を取得する方法を探しています。ログ解析の設定を日本語、英語と切り替えられるようにするための調査です。ネット上を探すとそのまま使えるサンプルが見つからないため、DelphiForFun HomeにあったDemoのコードを参考にしてサンプルコードを作りました。



試すときは、Formの上に、ButtonとListViewを配置し、ListViewの形式をvsReport、カラムを5つ定義してください。参考にしたのは以下のURLの情報です。
Locale Constants Demo

Language Tagの定義を探していたら、以下の情報が見つかりました。昔々、VAX Notes上でお世話になった記憶が微かにあります。
国際化プログラミング

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, shellapi, Vcl.ComCtrls;

type
  TForm1 = class(TForm)
    ListView1: TListView;
    Button1: TButton;
    procedure FormActivate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type
  TRec = Record
    Code: Cardinal;
    Name: String;
    Text: String;
  end;

const
  rSet: Array [0 .. 79] of TRec = (
    (Code: LOCALE_ILANGUAGE; Name: '言語ID'; Text: 'LOCALE_ILANGUAGE'),
    (Code: LOCALE_SLANGUAGE; Name: '言語名'; Text: 'LOCALE_SLANGUAGE'),
    (Code: LOCALE_SENGLANGUAGE; Name: '言語英語名'; Text: 'LOCALE_SENGLANGUAGE'),
    (Code: LOCALE_SABBREVLANGNAME; Name: '言語省略名'; Text: 'LOCALE_SABBREVLANGNAME'),
    (Code: LOCALE_SNATIVELANGNAME; Name: '言語固有名'; Text: 'LOCALE_SNATIVELANGNAME'),
    (Code: LOCALE_ICOUNTRY; Name: '国コード'; Text: 'LOCALE_ICOUNTRY'),
    (Code: LOCALE_SCOUNTRY; Name: '国名'; Text: 'LOCALE_SCOUNTRY'),
    (Code: LOCALE_SENGCOUNTRY; Name: '国英語名'; Text: 'LOCALE_SENGCOUNTRY'),
    (Code: LOCALE_SABBREVCTRYNAME; Name: '国省略名'; Text: 'LOCALE_SABBREVCTRYNAME'),
    (Code: LOCALE_SNATIVECTRYNAME; Name: '国固有名'; Text: 'LOCALE_SNATIVECTRYNAME'),
    (Code: LOCALE_IDEFAULTLANGUAGE; Name: 'デフォルト言語ID'; Text: 'LOCALE_IDEFAULTLANGUAGE'),
    (Code: LOCALE_IDEFAULTCOUNTRY; Name: 'デフォルト国コード'; Text: 'LOCALE_IDEFAULTCOUNTRY'),
    (Code: LOCALE_IDEFAULTCODEPAGE; Name: 'デフォルトOEMコードページ'; Text: 'LOCALE_IDEFAULTCODEPAGE'),
    (Code: LOCALE_IDEFAULTANSICODEPAGE; Name: 'デフォルトANSIコードページ'; Text: 'LOCALE_IDEFAULTANSICODEPAGE'),
    (Code: LOCALE_IDEFAULTMACCODEPAGE; Name: 'デフォルトMACコードページ'; Text: 'LOCALE_IDEFAULTMACCODEPAGE'),
    (Code: LOCALE_FONTSIGNATURE; Name: 'フォント署名'; Text: 'LOCALE_FONTSIGNATURE'),
    (Code: LOCALE_SISO639LANGNAME; Name: 'ISO言語省略名'; Text: 'LOCALE_SISO639LANGNAME'),
    (Code: LOCALE_SISO3166CTRYNAME; Name: 'ISO国省略名'; Text: 'LOCALE_SISO3166CTRYNAME'),
    (Code: LOCALE_SLIST; Name: '区切り記号'; Text: 'LOCALE_SLIST'),
    (Code: LOCALE_IMEASURE; Name: '単位'; Text: 'LOCALE_IMEASURE'),
    (Code: LOCALE_SDECIMAL; Name: '小数点の記号'; Text: 'LOCALE_SDECIMAL'),
    (Code: LOCALE_STHOUSAND; Name: '桁区切り記号'; Text: 'LOCALE_STHOUSAND'),
    (Code: LOCALE_SGROUPING; Name: '区切る桁数'; Text: 'LOCALE_SGROUPING'),
    (Code: LOCALE_IDIGITS; Name: '小数点以下の桁数'; Text: 'LOCALE_IDIGITS'),
    (Code: LOCALE_ILZERO; Name: '少数前ゼロの桁数'; Text: 'LOCALE_ILZERO'),
    (Code: LOCALE_INEGNUMBER; Name: '負の値の形式'; Text: 'LOCALE_INEGNUMBER'),
    (Code: LOCALE_SNATIVEDIGITS; Name: '0から9の表記'; Text: 'LOCALE_SNATIVEDIGITS'),
    (Code: LOCALE_SPOSITIVESIGN; Name: '正の記号'; Text: 'LOCALE_SPOSITIVESIGN'),
    (Code: LOCALE_SNEGATIVESIGN; Name: '負の記号'; Text: 'LOCALE_SNEGATIVESIGN'),
    (Code: LOCALE_IPOSSIGNPOSN; Name: '正の記号の位置'; Text: 'LOCALE_IPOSSIGNPOSN'),
    (Code: LOCALE_INEGSIGNPOSN; Name: '負の記号の位置'; Text: 'LOCALE_INEGSIGNPOSN'),
    (Code: LOCALE_SCURRENCY; Name: '通貨記号'; Text: 'LOCALE_SCURRENCY'),
    (Code: LOCALE_SINTLSYMBOL; Name: '国際通貨記号'; Text: 'LOCALE_SINTLSYMBOL'),
    (Code: LOCALE_SMONDECIMALSEP; Name: '小数点の記号'; Text: 'LOCALE_SMONDECIMALSEP'),
    (Code: LOCALE_SMONTHOUSANDSEP; Name: '桁区切り記号'; Text: 'LOCALE_SMONTHOUSANDSEP'),
    (Code: LOCALE_SMONGROUPING; Name: '区切る桁数'; Text: 'LOCALE_SMONGROUPING'),
    (Code: LOCALE_ICURRDIGITS; Name: '小数点以下の桁数'; Text: 'LOCALE_ICURRDIGITS'),
    (Code: LOCALE_IINTLCURRDIGITS; Name: '小数点以下の桁数'; Text: 'LOCALE_IINTLCURRDIGITS'),
    (Code: LOCALE_ICURRENCY; Name: '正の値の形式'; Text: 'LOCALE_ICURRENCY'),
    (Code: LOCALE_INEGCURR; Name: '負の値の形式'; Text: 'LOCALE_INEGCURR'),
    (Code: LOCALE_IPOSSYMPRECEDES; Name: '正の通貨記号の位置'; Text: 'LOCALE_IPOSSYMPRECEDES'),
    (Code: LOCALE_IPOSSEPBYSPACE; Name: '正の通貨記号の分離位置'; Text: 'LOCALE_IPOSSEPBYSPACE'),
    (Code: LOCALE_INEGSYMPRECEDES; Name: '負の通貨記号の位置'; Text: 'LOCALE_INEGSYMPRECEDES'),
    (Code: LOCALE_INEGSEPBYSPACE; Name: '負の通貨記号の分離位置'; Text: 'LOCALE_INEGSEPBYSPACE'),
    (Code: LOCALE_SDATE; Name: '区切り記号'; Text: 'LOCALE_SDATE'),
    (Code: LOCALE_SSHORTDATE; Name: '短い形式'; Text: 'LOCALE_SSHORTDATE'),
    (Code: LOCALE_SLONGDATE; Name: '長い形式'; Text: 'LOCALE_SLONGDATE'),
    (Code: LOCALE_IDATE; Name: '短い形式の年月日順'; Text: 'LOCALE_IDATE'),
    (Code: LOCALE_ILDATE; Name: '長い形式の年月日順'; Text: 'LOCALE_ILDATE'),
    (Code: LOCALE_ICENTURY; Name: '年の桁数'; Text: 'LOCALE_ICENTURY'),
    (Code: LOCALE_IDAYLZERO; Name: '日前ゼロの有無'; Text: 'LOCALE_IDAYLZERO'),
    (Code: LOCALE_IMONLZERO; Name: '月前ゼロの有無'; Text: 'LOCALE_IMONLZERO'),
    (Code: LOCALE_ICALENDARType; Name: 'カレンダの種類'; Text: 'LOCALE_ICALENDARType'),
    (Code: LOCALE_IOPTIONALCALENDAR; Name: '追加カレンダの種類'; Text: 'LOCALE_IOPTIONALCALENDAR'),
    (Code: LOCALE_IFIRSTDAYOFWEEK; Name: '週の先頭日'; Text: 'LOCALE_IFIRSTDAYOFWEEK'),
    (Code: LOCALE_IFIRSTWEEKOFYEAR; Name: '年の先頭月'; Text: 'LOCALE_IFIRSTWEEKOFYEAR'),
    (Code: LOCALE_SDAYNAME1; Name: '週の第1日名'; Text: 'LOCALE_SDAYNAME1'),
    (Code: LOCALE_SDAYNAME2; Name: '週の第2日名'; Text: 'LOCALE_SDAYNAME2'),
    (Code: LOCALE_SDAYNAME3; Name: '週の第3日名'; Text: 'LOCALE_SDAYNAME3'),
    (Code: LOCALE_SDAYNAME7; Name: '週の第7日名'; Text: 'LOCALE_SDAYNAME7'),
    (Code: LOCALE_SABBREVDAYNAME1; Name: '週の第1日省略名'; Text: 'LOCALE_SABBREVDAYNAME1'),
    (Code: LOCALE_SABBREVDAYNAME2; Name: '週の第2日省略名'; Text: 'LOCALE_SABBREVDAYNAME2'),
    (Code: LOCALE_SABBREVDAYNAME3; Name: '週の第3日省略名'; Text: 'LOCALE_SABBREVDAYNAME3'),
    (Code: LOCALE_SABBREVDAYNAME7; Name: '週の第7日省略名'; Text: 'LOCALE_SABBREVDAYNAME7'),
    (Code: LOCALE_SMONTHNAME1; Name: '年の第1月名'; Text: 'LOCALE_SMONTHNAME1'),
    (Code: LOCALE_SMONTHNAME2; Name: '年の第2月名'; Text: 'LOCALE_SMONTHNAME2'),
    (Code: LOCALE_SMONTHNAME3; Name: '年の第3月名'; Text: 'LOCALE_SMONTHNAME3'),
    (Code: LOCALE_SMONTHNAME12; Name: '年の第12月名'; Text: 'LOCALE_SMONTHNAME12'),
    (Code: LOCALE_SMONTHNAME13; Name: '年の第13月名'; Text: 'LOCALE_SMONTHNAME13'),
    (Code: LOCALE_SABBREVMONTHNAME1; Name: '年の第1月省略名'; Text: 'LOCALE_SABBREVMONTHNAME1'),
    (Code: LOCALE_SABBREVMONTHNAME2; Name: '年の第2月省略名'; Text: 'LOCALE_SABBREVMONTHNAME2'),
    (Code: LOCALE_SABBREVMONTHNAME3; Name: '年の第3月省略名'; Text: 'LOCALE_SABBREVMONTHNAME3'),
    (Code: LOCALE_SABBREVMONTHNAME12; Name: '年の第12月省略名'; Text: 'LOCALE_SABBREVMONTHNAME12'),
    (Code: LOCALE_STIME; Name: '区切り記号'; Text: 'LOCALE_STIME'),
    (Code: LOCALE_STIMEFORMAT; Name: '時間の形式'; Text: 'LOCALE_STIMEFORMAT'),
    (Code: LOCALE_ITIME; Name: '時間制(12/24)'; Text: 'LOCALE_ITIME'),
    (Code: LOCALE_ITIMEMARKPOSN; Name: '午前午後記号の位置'; Text: 'LOCALE_ITIMEMARKPOSN'),
    (Code: LOCALE_ITLZERO; Name: '時刻前ゼロの有無'; Text: 'LOCALE_ITLZERO'),
    (Code: LOCALE_S1159; Name: '午前の記号'; Text: 'LOCALE_S1159'),
    (Code: LOCALE_S2359; Name: '午後の記号'; Text: 'LOCALE_S2359')
  );

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Form1.Close;
end;

procedure TForm1.FormActivate(Sender: TObject);
var
  buf: array [1 .. 100] of char;
  i: integer;
  AItem: TListItem;
begin
  for i := Low(rSet) to High(rSet) do
  begin
    Windows.GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, rSet[i].Code, @buf, 100);

    AItem := ListView1.Items.Add;
    AItem.Caption := Format('%.3d', [i + 1]);
    AItem.SubItems.Add(rSet[i].Name);
    AItem.SubItems.Add(rSet[i].Text);
    AItem.SubItems.Add(Format('%d', [rSet[i].Code]));
    AItem.SubItems.Add(string(buf));
  end;

end;

end.

2016年1月4日月曜日

AdvListViewのソートを使う方法

実装を何度も忘れたのでメモします。
AdvListViewでソートを使うためには以下の設定が必要です。

  • SortShow := True を設定
  • AdvListViewの各カラムにTagの番号を設定します。
  • イベント OnColumnClick のハンドラを定義しその中で
  • SortColumnをカラムのタグから指定

procedure TForm1.AdvListView1ColumnClick(Sender: TObject; Column: TListColumn);
var
  tag: integer;
begin

  tag := Column.Tag;
  AdvListView1.SortColumn := tag;

end;
便利!

SAS Log Utility 1.6.1.5, 文字列のパターンをINIファイルで定義

年末年始の休みを使って、SAS Log Utilityを更新しました。
  • 潜在的な問題のパターンをINIファイルに定義
  • ログを解析するためのパターンをINIファイルに定義

Vectorに新バージョンの登録を依頼しました。SAS Log Utilityは仕事でもっとも良く使うツールです。これまで、SASのバージョンアップの度に、マッチングのパターンを変えてはビルドしていました。とはいえ、いつも同じバージョンのSASを使っていないので、その都度直してビルドするのは面倒です。そんな理由で、設定のフォームを作って修正できるようにしました。

追加したOptionsのメニュー


バグに繋がりそうなNOTE:のパターン


処理時間、データセット名を捕捉するためのパターン定義
マッチングのパターンですが、"Keyword Setting"では、データセット名やファイル名などのメタ文字を定義できるようにしました。たとえば"[:dsn:]"でデータセット名のパターンを定義します。これは、Nリテラルのデータセット名をすっきりと定義、参照するために実装した機能です。


定義しているパターン(Keyword)の件数は固定です。このパターンは、行の種類を特定するためと、行の中に含まれる情報を抽出するための2種類があります。情報を抽出するとは、「999 オブザベーション」とかのデータ数、データセット名、ファイル名などを取り出すことです。

それと英語のパターン定義は、外しました。将来、多言語対応で設定を切り替えられるようにするため、いったんパターンから外しました。

INIファイルの書式が、桁固定で分かりにくいが、それはゆくゆく直します。いまは使えることの方が大事なので後回しです。

2014年5月3日土曜日

Delphi XE6 + Excel2013のタイプライブラリ

Delphi XE6とExcel2013の組み合わせで開発していますが、Excelのタイプライブラリが取り込めません。以前は、この「EXCEL2010を操作してみる」の解説どおりできていたのですが、バージョンがあがったためか, いつのころからか、登録済みのタイプライブラリに含まれなくなっていました。


事情は良くわからぬものの、"C:\Program Files (x86)\Embarcadero\Studio\14.0\OCX\Servers\Excel2010.pas" をプロジェクトに追加して騙しだましでビルドしています。

SAS Option Report 1.3.0.6

SAS 9.4のバージョンアップ作業に備えて、SAS Option Reportを更新しました。
微妙に字句が変わっているので、以前のバージョンではうまく設定値を拾うことが出来ませんでした。字句定義を変えて、Delphi XE6でリビルドしています。


次もまた仕事で使うツール手直ししないといけません。
埃をかぶっているSRXはまた出番がありそうです。

2014年5月1日木曜日

Delphi XE6でバージョン情報を取得, GetFileVersionInfo

Delphi XE2に乗り換えてから、既存のコードでバージョン情報が取れなくなりました。気合を入れなおして、サンプルコードを探し出して修正しました。XE6でも動作確認取れました。

unit version;

interface

type
  TEXEVersionData = record
    CompanyName,
    FileDescription,
    FileVersion,
    InternalName,
    LegalCopyright,
    LegalTrademarks,
    OriginalFileName,
    ProductName,
    ProductVersion,
    Comments,
    PrivateBuild,
    SpecialBuild: string;
  end;

var
  theVersion: TEXEVersionData;

implementation

uses Windows, SysUtils, Forms;

procedure LoadVersionInfo;
type
  PLandCodepage = ^TLandCodepage;
  TLandCodepage = record
    wLanguage,
    wCodePage: word;
  end;
var
  dummy,
  len: cardinal;
  buf, pntr: pointer;
  lang, key: string;
begin
  len := GetFileVersionInfoSize(PChar(Application.ExeName), dummy);
  if len = 0 then
    RaiseLastOSError;
  GetMem(buf, len);
  try
    if not GetFileVersionInfo(PChar(Application.ExeName), 0, len, buf) then
      RaiseLastOSError;

    if not VerQueryValue(buf, '\VarFileInfo\Translation\', pntr, len) then
      RaiseLastOSError;

    lang := Format('%.4x%.4x', [PLandCodepage(pntr)^.wLanguage, PLandCodepage(pntr)^.wCodePage]);

    key := '\StringFileInfo\' + lang + '\CompanyName';
    if VerQueryValue(buf, PChar(Key), pntr, len) then
      theVersion.CompanyName := PChar(pntr);
    key := '\StringFileInfo\' + lang + '\FileDescription';
    if VerQueryValue(buf, PChar(key), pntr, len) then
      theVersion.FileDescription := PChar(pntr);
    key := '\StringFileInfo\' + lang + '\FileVersion';
    if VerQueryValue(buf, PChar(key), pntr, len) then
      theVersion.FileVersion := PChar(pntr);
    key := '\StringFileInfo\' + lang + '\InternalName';
    if VerQueryValue(buf, PChar(key), pntr, len) then
      theVersion.InternalName := PChar(pntr);
    key := '\StringFileInfo\' + lang + '\LegalCopyright';
    if VerQueryValue(buf, PChar(key), pntr, len) then
      theVersion.LegalCopyright := PChar(pntr);
    key := '\StringFileInfo\' + lang + '\LegalTrademarks';
    if VerQueryValue(buf, PChar(key), pntr, len) then
      theVersion.LegalTrademarks := PChar(pntr);
    key := '\StringFileInfo\' + lang + '\OriginalFileName';
    if VerQueryValue(buf, PChar(key), pntr, len) then
      theVersion.OriginalFileName := PChar(pntr);
    key := '\StringFileInfo\' + lang + '\ProductName';
    if VerQueryValue(buf, PChar(key), pntr, len) then
      theVersion.ProductName := PChar(pntr);
    key := '\StringFileInfo\' + lang + '\ProductVersion';
    if VerQueryValue(buf, PChar(key), pntr, len) then
      theVersion.ProductVersion := PChar(pntr);
    key := '\StringFileInfo\' + lang + '\Comments';
    if VerQueryValue(buf, PChar(key), pntr, len) then
      theVersion.Comments := PChar(pntr);
    key := '\StringFileInfo\' + lang + '\PrivateBuild';
    if VerQueryValue(buf, PChar(key), pntr, len) then
      theVersion.PrivateBuild := PChar(pntr);
    key := '\StringFileInfo\' + lang + '\SpecialBuild';
    if VerQueryValue(buf, PChar(key), pntr, len) then
      theVersion.SpecialBuild := PChar(pntr);
  finally
    FreeMem(buf);
  end;
end;

initialization
  LoadVersionInfo;

end.