0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

EXCEL-VBAでバイナリファイル。COBOLファイル。

Last updated at Posted at 2024-01-28

やりたかったこと

セキュリティエリア内で自由に使える開発言語が(悲しいことに)EXCEL-VBAぐらいしかない案件があり、C言語やPerlで自作したツールを持ち込めそうにないので、VBAでバイナリファイル(某社COBOLファイル)を扱えるものを作った。

残念なこと

EXCEL-VBAでは、2G以上のファイルを扱えない。
2Gまでは処理を進めるが、突然エラーMSGを出して止まってしまう。内部ではファイルポインタを使っているが、32ビット(2^31)になっていると想像。

アウトライン

  • UI:EXCELブックから、マクロを起動。マクロでEXCELシートから入力・出力・ログのファイル名やファイル属性を取得し、マクロ(sub)を起動する。
  • 主たるマクロ
    • ex_byte2hex : バイナリファイルを16進テキストファイルに変換
    • ex_hex2byte : 16進テキストファイルをバイナリファイルに変換
  • vbaのコードはgistに置いてある
    EXCEL-VBAでバイナリファイル

EXCEL

ボタン

ボタンに、ex_byte2hex , ex_hex2byte を割り当てる

固定長のCOBOLファイル

スクリーンショット 2024-01-28 17.13.30.png

固定長[recfm=f]を指定した時

  • ex_byte2hexは、lreclバイトを1レコードとして[lrecl*2の16進文字列+改行(CR,LF)]のテキストファイル1行にする。
  • ex_hex2byteは、テキストファイル1行[16進文字列+改行(CR,LF)]を、2文字毎にバイト列とし固定長COBOLファイル化する。
16進テキスト(固定長)
0C000000303132331020304C41424344
0C00000010000000313233341020304D
42434445012345671000000010000000
323334352030405C4344454612345678
100000000C000000333435362030405C
444546470C0000001000000034353637
3040506C454647482345678910000000

可変長のCOBOLファイル

スクリーンショット 2024-01-28 17.25.58.png

可変長(recfm=v)を指定した時

  • ex_byte2hexは、COBOL可変長の1レコード[LL + バイト列 + LL]を16進テキスト1行にする。
  • ex_hex2byteは、テキスト1行[16進文字列+改行(CR,LF)]を2文字ごとにバイト列にして、COBOL可変長の1レコード[LL + バイト列 + LL]にする。
  • 某社のCOBOL可変長ファイルは、LLが[2byteのLittleEndianのbinary + 0x0000]なので、VBAでは4byteのLittleEndianであるLong型を使っている。
16進テキスト(可変長)
303132331020304C41424344
313233341020304D4243444501234567
323334352030405C4344454612345678
333435362030405C44454647
343536373040506C4546474823456789

バイナリファイルを扱う

オープン・入力

binary-open-read
fno = FreeFile
Open f.fname For Binary Access Read As #fno

オープン・出力

binary-open-write
fno = FreeFile
Open f.fname For Binary Access Write As #fno

読み込み(Byte型)

Byte属性の配列を定義し、その要素数バイトを読み込む

binary-get
' 読み込みサイズ分のバイト列を用意
    Dim bBuf() As Byte
    ReDim bBuf(0 To lrecl - 1)
'
' lrecl(bBuf)バイトを読む
'
' ============================================================
    Get #fno, , bBuf
' ============================================================
    If EOF(fno) = True Then
        f.iseof = FCNTL_EOF
    End If

読み込み(Long型)

4バイトの整数を読み込む例。可変長COBOLファイルのレコード長(LL)がこの型なので。

binary-getLL
    Dim ll As Long
    Get #fno, , ll
'
    If EOF(fno) = True Then
        f.iseof = FCNTL_EOF
    End If

書き込み(バイト型)

Byte属性の配列を定義し、その要素数バイトを書き込む

binary-write
    Dim buf() As Byte
    ReDim buf(0 To lrecl - 1)
    Dim i As Integer
    For i = 0 To lrecl - 1
        buf(i) = bytes(i)
    Next i
' ================================
    Put #fno, , buf
' ================================

書き込み(整数、Long)

4バイト整数の書き込み。可変長COBOLのレコード長(LL)がこの型なので。

binary-writeLL
    Dim lrecl as Long
'
    fno = f.fileno
    Put #fno, , lrecl
'

テキストファイルを扱う

ログファイルは無条件にテキストファイルで扱う。

オープン・入力

text-open-input
fno = FreeFile
Open f.fname For Input As #fno

オープン・出力

text-open-output
fno = FreeFile
Open f.fname For Output As #fno

読み込み(テキスト)

text-input
' テキスト1行を読込。最終行を読み込んだ時に、EOFが帰ってくるので、EOFでも返却域の設定を行う
' ================================================================
    Line Input #fno, buf
' ================================================================
    If EOF(fno) = True Then
        f.iseof = FCNTL_EOF
    End If

書き込み(テキスト)

text-print
    fno = f.fileno
    Print #fno, buf

バイナリ・テキスト共通

クローズ

close
Close #fno

ファイル属性の構造体

上のソースで、f.xxxはこの構造体のメンバ

Fcntl
Type Fcntl
    fileno As Integer       ' ファイル番号。#をつけて参照
    fname As String         ' ファイル名
    recfm As String         ' f|v|t / 固定長(f)、可変長(v)、テキスト(t)
    lrecl As Integer        ' 固定長:レコード長、可変長:最大長
    isopened As Integer     ' 0|1 / 0:NotOpened, 1:Opened
    iocnt As Long           ' 入出力件数
    mode As String          ' i|o / i:inpupt, o:output
    maxbuf As Long          ' bufの最大、inputは3200, outputは64000
    iseof As Integer        ' 0:notEOF, 1:EOF
End Type
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?