Delphi/400で取得した文字や数値のデータを、
他システムと連携するために成型したテキストにする局面があるかと思います。
逆に、他システムから成型されたテキストで受け取ったものをIBM i に更新する機会もあるかと思います。
今回はそのような際の文字列操作の手順をご紹介します。
<データ型の凡例>
今回は以下のようなデータを受け渡す想定でロジックを作成します。
| フィールドID | 項目名 | IBM i 側の型と桁数 | 固定長テキストでの位置 |
|---|---|---|---|
| WS0001 | 受注NO | 半角文字10桁 (10A) | 1~10桁目 |
| WS0002 | 品番 | 半角文字10桁 (10A) | 11~20桁目 |
| WS0003 | 受注日 | 整数8桁(8P0) ※YYYYMMDD | 21~28桁目 |
| WS0004 | 単価 | 整数6桁(6P0) | 29~34桁目 |
| WS0005 | 仕入先CD | 半角文字6桁 (6A) | 35~40桁目 |
| WS0006 | 伝達事項 | 全半角文字60桁 (60O) | 41~100桁目 |

<IBM i ⇒ 固定長テキストの変換ロジック>
以下のようにロジックを記述することで、
文字フィールドは余白部分をスペース埋め、数値フィールドは0埋めして
固定長テキストを生成可能です。
バイト単位にするため、文字列はAnsiStringとして処理を行います。
{*******************************************************************************
半角文字(A)・全半角混在(O)をバイト長で右側空白埋め
*******************************************************************************}
function PadRightAnsi(const S: AnsiString; Len: Integer): AnsiString;
var
BLen: Integer;
begin
Result := S;
BLen := Length(Result); // AnsiStringなのでバイト長
if BLen < Len then
Result := Result + AnsiString(StringOfChar(' ', Len - BLen))
else if BLen > Len then
SetLength(Result, Len);
end;
{*******************************************************************************
数値(P)を左側0埋め
*******************************************************************************}
function PadLeftZeroInt(const N: Integer; Len: Integer): AnsiString;
begin
Result := AnsiString(Format('%.*d', [Len, N]));
end;
{*******************************************************************************
PadRightAnsiとPadLeftZeroIntを使って空白埋めと0埋めされた文字列の作成
*******************************************************************************}
function BuildFixedText(
const A_JuchuNo : AnsiString; // WS0001 A(10)
const A_Hinban : AnsiString; // WS0002 A(10)
const P_JuchuDate : Integer; // WS0003 P(8) yyyymmdd
const P_Tanka : Integer; // WS0004 P(6)
const A_ShiireCd : AnsiString; // WS0005 A(6)
const O_Message : AnsiString // WS0006 O(60)
): AnsiString;
var
Buf: AnsiString;
begin
Buf := '';
// 1~10 受注NO
Buf := Buf + PadRightAnsi(A_JuchuNo, 10);
// 11~20 品番
Buf := Buf + PadRightAnsi(A_Hinban, 10);
// 21~28 受注日
Buf := Buf + PadLeftZeroInt(P_JuchuDate, 8);
// 29~34 単価
Buf := Buf + PadLeftZeroInt(P_Tanka, 6);
// 35~40 仕入先コード
Buf := Buf + PadRightAnsi(A_ShiireCd, 6);
// 41~100 伝達事項(全半角混在・60バイト)
Buf := Buf + PadRightAnsi(O_Message, 60);
Result := Buf; // 全長100バイト
end;
{*******************************************************************************
ボタン押下時処理(イメージ)
※今回のサンプルでは1行だが実際にはQueryのBOF~EOFまで繰り返す
*******************************************************************************}
procedure TForm1.Button1Click(Sender: TObject);
var
Line: AnsiString;
begin
// 空白埋めと0埋めされた文字列の作成
Line := BuildFixedText(
FDQuery1.FieldByName('WS0001').AsString, // 受注NO
FDQuery1.FieldByName('WS0002').AsString, // 品番
FDQuery1.FieldByName('WS0003').AsInteger, // 受注日
FDQuery1.FieldByName('WS0004').AsInteger, // 単価
FDQuery1.FieldByName('WS0005').AsString, // 仕入先コード
FDQuery1.FieldByName('WS0006').AsString // 伝達事項(全角)
);
// 作成された文字列の表示
//(実際にはテキストに順次出力 https://www.migaro.co.jp/tips/102/ )
ShowMessage(Line);
Edit2.Text := Line;
end;
<固定長テキスト ⇒ IBM i の変換ロジック>
以下のようにロジックを記述することで、
固定長テキストの桁ごとに文字を区切り、IBM i にSQLで更新するロジックを記述可能です。
{*******************************************************************************
ボタン押下時処理(イメージ)
※今回のサンプルでは1行だが実際にはテキストの先頭~最終行まで繰り返す
*******************************************************************************}
procedure TForm1.Button2Click(Sender: TObject);
var
Line: AnsiString;
JuchuNo : AnsiString; // A(10)
Hinban : AnsiString; // A(10)
JuchuDate : Integer; // P(8)
Tanka : Integer; // P(6)
ShiireCd : AnsiString; // A(6)
Dentatsu : AnsiString; // O(60)
begin
// パラメータSQL設定
FDQuery2.SQL.Text :=
' INSERT INTO C12512P ( ' +
' WS0001, WS0002, WS0003, WS0004, WS0005, WS0006 ' +
' ) VALUES ( ' +
' :WS0001, :WS0002, :WS0003, :WS0004, :WS0005, :WS0006 )';
//(以下、実際にはテキストの行単位で行う)
// 固定長の文字列を変数にセット
Line := AnsiString(Edit2.Text);
// 固定位置で変数に切り出し
JuchuNo := Copy(Line, 1, 10); // 受注NO
Hinban := Copy(Line, 11, 10); // 品番
JuchuDate := StrToIntDef(Copy(Line, 21, 8), 0); // 受注日
Tanka := StrToIntDef(Copy(Line, 29, 6), 0); // 単価
ShiireCd := Copy(Line, 35, 6); // 仕入先コード
Dentatsu := Copy(Line, 41, 60); // 伝達事項(全角)
// パラメータセット
FDQuery2.ParamByName('WS0001').AsString := JuchuNo; // 受注NO
FDQuery2.ParamByName('WS0002').AsString := Hinban; // 品番
FDQuery2.ParamByName('WS0003').AsInteger := JuchuDate; // 受注日
FDQuery2.ParamByName('WS0004').AsInteger := Tanka; // 単価
FDQuery2.ParamByName('WS0005').AsString := ShiireCd; // 仕入先コード
FDQuery2.ParamByName('WS0006').AsString := Dentatsu; // 伝達事項(全角)
// 更新SQL実行
FDQuery2.ExecSQL;
//(実際にはテキストの行単位で行う処理ここまで)
end;
<IBM i 内のデータと固定長テキストのイメージ>

- <※ご注意事項>
- バイト数の判定にAnsiStringを使用しているため、
JP-4(CCSID 1399)で使用可能なUnicode依存文字には対応しておりません。 - 本ページのサンプルでは、IBM i への変換時のシフト文字の考慮を行っておりません。
全角文字更新時の桁あふれエラー対策については別途こちらのTipsをご覧ください。
またAnsiStringで複雑な文字列処理を必要とする場合はこちらのTipsもご参照ください。 - 本ページに掲載しているソースコードは情報提供の為のサンプルプログラムとなります。
お客様作成アプリケーション内で自由にご利用いただけます。
ただし、これらのソースコードやサンプルプログラムを使用したことによって生じた、
いかなる障害・損失に関しても一切の責を負いかねますので、ご了承下さい。
- バイト数の判定にAnsiStringを使用しているため、