はじめまして。てつこと申します。
こんな事で質問しては申し訳ないかとは思いましたが、
万策つきてしまいましたので、お力をお貸しください。
SQLサーバからデータを抽出し、固定長テキストファイルにはきだすのですが、
テキストファイルにはきだす際、数値をパック十進数に変換しなければなりません。
現在はFTRANを使用して返還しているのですが、このツールを使用せずに
変換する必要が出た為、方法を探したのですがどうしてもみつかりません。
方法をご存知な方がいらっしゃいましたら、ぜひご教授ください。
OSはWin2000/XPです。VBは6.0を使用しています。
よろしくお願い致します。
まず、私はパック十進数なるものをしらないので、Google先生に聞いてみました。
→結果: http://tinyurl.com/a5jll
得られた結果からすると、以外と簡単にゴリゴリ書ける気がします。
まぁ、それだけですが。(ぇ
こういうのは意外とテーブル参照が楽だったりします。
合ってるかどうか判らんし、どう見ても醜いコードがけど
参考に。
Private Function Pack10(ByVal iData As Long) As String
Dim ss As String
Dim pData As String
Dim sData As String
Dim d(11) As String
Dim i As Long
d(0) = "0000": d(1) = "0001": d(2) = "0010"
d(3) = "0011": d(4) = "0100": d(5) = "0101"
d(6) = "0110": d(7) = "0111": d(8) = "1000"
d(9) = "1001": d(10) = "1100": d(11) = "1101"
sData = CStr(iData)
If Left(sData, 1) <> "-" And Left(sData, 1) <> "+" Then
sData = "+" & sData
End If
For i = Len(sData) To 1 Step -1
ss = Mid(sData, i, 1)
If ss = "+" Then
pData = pData & " " & d(10)
ElseIf ss = "-" Then
pData = pData & " " & d(11)
Else
pData = d(Val(ss)) & " " & pData
End If
Next
Pack10 = pData
End Function
ガッ様、ねろ様 ご回答ありがとうございました。
おかげ様でパック十進数なるものが大分わかりました。
そこで更なる質問なのですが、
以下の様な出力文字列を編集するロジックを組んだ時、
[rs.Fields(1)]に[432]という値が入っていた場合、
パック十進数に置き換えると[0100001100101100]となる事は
分かりましたが、実際に[0100001100101100]という値を
パック十進数の値として出力する方法がわかりません。
ご教授の程、よろしくお願い致します。
Function sLinStr(rs As Recordset) As String
Dim sStr As String
'変数クリア
sStr = ""
'8桁の値を日付表示に変換
sStr = Format(rs.Fields(0), "0000/00/00") & ";"
'パック十進数に変換
sStr = rs.Fields(1) & ";"
'後ろにスペースを5桁を追加
sStr = rs.Fields(2) & String$(5, " ")
sLinStr = sStr
End Function
先ず私が書いた関数に好きな数字を入れて何が返って来るか見てから
再度質問して下さい。
ねろ様
先日ロジックを提示して頂いた時に、即実行してみました。
[432]という値を入れて実行すると[0100 0011 0010 1100]が
帰ってくる事は確認しております。
(折角提示して頂いたものを確認もしないような失礼は致しません。)
この[432]を[0100 0011 0010 1100]に変換した後、
2バイトの領域に格納する為に更に変換が必要なのではないかと
思うのですが、その方法がわからず困っています。
「そんな初歩的な事もわからんのか!」とお叱りを受けるかも
しれませんが、現実にわからないのです。
どうぞ、よろしくご教授ください。
>SQLサーバからデータを抽出し、固定長テキストファイルにはきだすのですが、
>テキストファイルにはきだす際、数値をパック十進数に変換しなければなりません。
データーを固定長のパック十進数にしてテキストファイルにした、元のデーターと
変換されたテキストのサンプルは有りませんか?
残念ながら、今手元には変換後のデータしかありません。
何が問題なのか理解してないね(^^;)。とりあえず
http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200506/05060170.txt
を読んでみて?。
>Dental 2005/06/29(水) 16:49:12
で Dental さんがリンク貼ってくれてるような認識が必要です。
最初の質問で
>SQLサーバからデータを抽出し、固定長テキストファイルにはきだすのですが、
>テキストファイルにはきだす際、数値をパック十進数に変換しなければなりません。
とありますが、テキストファイルというと、Notepad なんかで開いて読める文字、
…つまりVBで扱うなら String 型の『文字列』に変換したい…という質問になります。
ですから、ねろさんはわざわざ String 型の『文字列』を返してくれてるサンプルを
提示して下さいました。N進数の文字列が欲しい。つまり"0100 0011 0010 1100"と
いう文字列データが最終結果として欲しいという質問だからです。
>この[432]を[0100 0011 0010 1100]に変換した後、
>2バイトの領域に格納する為に更に変換が必要なのではないかと
>思うのですが、その方法がわからず困っています。
ここで、2バイトという表現で書き出すのがテキストファイルでなく、
バイナリファイルである可能性が出てきてしまいました。更に、2バイトの
『何』が欲しいのか分からなくなってしまいました。
>現在はFTRANを使用して返還しているのですが、このツールを使用せずに
>変換する必要が出た為、方法を探したのですがどうしてもみつかりません。
そのFTRANとやらの前後で入力と出力のデータ型を明らかにして下さい。
また、その具体的なデータを示して下さい。
例えば
Dim wInputData As Integer
Dim wOutputData(1) As Byte
wInputData = 432 '入力(数値型[2Byte]10進数表現で 432)
wOutputData = FTRAN(wInputData) 'パック十進数変換
'wOutputData(0) は2進数表現で 01000011(10進数表現で 67)
'wOutputData(1) は2進数表現で 00101100(10進数表現で 44)
特攻隊長まるるうさんのレス完璧で、これ以上付け加えることは有りませんが、
>残念ながら、今手元には変換後のデータしかありません
変換後のデーターが有れば目的の96.3%位は達成できますが。
と言うか、八百屋に行って「大根と人参下さい」と言ったら
人参が無いんでと言って、大根も出てこないような。。。。。
こんな感じになります。
[ ]の部分が変換後の文字です。
01○○株式会社 ○○株式会社△支店
>[ ]の部分が変換後の文字です。
>01○○株式会社 ○○株式会社△支店
括弧はどこ?
要するに表現できない文字ですね。
Dim s As String
Dim i As Integer
Dim ss As String
s = ". ."
For i = 1 To Len(s)
ss = ss & " " & CStr(Asc(Mid(s, i, 1)))
Next
Debug.Print ss
「. .」の替わりに変換後の文字を入れて
ssを教えてください。
この場合の結果は、「バイナリデータ」になりますよね。
可読文字になるとは限らないので、テキストデータとしては
扱えないでしょう。Stringではなく、Byte配列で処理してください。
パック10進数は、私も(聞いたことはあれど)内容までは知らなかったので、
下記の説明記事を参考にして、VB6のコードに起こしてみましたが……
これで良いのかな。
http://www.jtw.zaq.ne.jp/kayakaya/new/kihon/text/zonepack.htm
'-------------
Public Function Pack(ByVal Value As Long) As Byte()
Dim BCD() As Byte
Dim sDec As String
Dim Length As Integer, Limit As Integer
Dim Pos As Integer, C As Byte
Dim Index As Integer
sDec = StrReverse(CStr(Abs(Value)))
Length = Len(sDec)
Limit = Length \ 2
ReDim BCD(Limit)
BCD(Limit) = IIf(Value >= 0, &HC, &HD)
Index = Limit
For Pos = 1 To Length
C = CByte(Mid(sDec, Pos, 1))
If Pos Mod 2 = 1 Then
BCD(Index) = C * &H10 + BCD(Index)
Index = Index - 1
Else
BCD(Index) = C
End If
Next
Pack = BCD
End Function
>この[432]を[0100 0011 0010 1100]に変換した後、
>2バイトの領域に格納する為に更に変換が必要なのではないかと
>思うのですが、その方法がわからず困っています。
ビットイメージをByte配列に格納するのはそんなに
難しいことではない。
'呼び出し方
Dim byt() As Byte
byt = GetPack10Byte(432)
Private Function GetPack10Byte(ByVal Value As Long) As Byte()
s = Pack10(Value)
s = Replace(s, " ", "") '空白行の削除
GetPack10Byte = BitToByte(s)
End Function
Private Function BitToByte(s)
'ビットイメージをByte配列に
Dim byt() As Byte
Dim i As Integer
Dim s1 As String
If Len(s) Mod 8 <> 0 Then
s = "0000" & s 'Byteに揃える
End If
ReDim byt(Len(s) \ 8 - 1) 'Byte配列の確保
Do
s1 = Left(s, 8)
byt(i) = BitToLong(s1)
s = Right(s, Len(s) - 8)
i = i + 1
Loop While (Len(s) <> 0)
BitToByte = byt
End Function
Private Function BitToLong(ByVal s As String) As Long
'ビット表示をLongに変換
Dim i As Integer
Dim t As Long
For i = 1 To Len(s)
If Mid(s, i, 1) = "1" Then
t = t + 2 ^ (Len(s) - i)
End If
Next
BitToLong = t
End Function
これで多分魔界の仮面弁士さんの処理結果と同じになるはずだが。。。。
まあこんな回りくどい方法にすることは無いのだが、行きがかり上やむおえず。orz
ツイート | ![]() |