Migaro. 技術Tips

                       

ミガロ. 製品の技術情報
IBMiの活用に役立つ情報を掲載!


【Delphi/400】固定長テキストの作成テクニック

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もご参照ください。
    • 本ページに掲載しているソースコードは情報提供の為のサンプルプログラムとなります。
      お客様作成アプリケーション内で自由にご利用いただけます。
      ただし、これらのソースコードやサンプルプログラムを使用したことによって生じた、
      いかなる障害・損失に関しても一切の責を負いかねますので、ご了承下さい。