Zaurus部屋 品書きへ


46.改行コード変換 for MS Access

 事始め副産物。

 Zaurusのパーソナルデータベース(PDB(II))とMS Accessは、ザウルスパワーリンク for Microsoft Access 2000/97を使えば相互にやりとりできる。
 ところであのう、Zaurus Support Stationの機種別に行くと、これへのリンクがあるんだけれど、なぜかMI-EX1のとこにしかない。E1にもC1にも載ってない。なんでじゃ。
 確か去年の暮れにも"PDB IIユーティリティへのリンクが消えてる"って騒いだが、どうもなぁ、これと思って探すと、ぽちぽち抜けているみたい。いけませんよ、ちゃんとのっけといてくださいな。

 で、やりとりはできるんだけれども、改行コードが反映されてくれない、ってのが困りもので...
 PDB(II)からAccessに持っていった場合、PDB(II)の改行はAccess上ではナカグロで表示され、くっついてしまう。逆も同じで(ナカグロにはならんけれど)、やはり改行されずにひっつく。


 わかっちゃいたけどほおっておいたのは、一つには、特段支障がなかったから。
 私がPDB IIで扱うDBは基本的には二通りで、仕事のトラブルDBと個人的な日記。これ、トラブルDBは職場でAccess使って入力しているし(みんなで、ね)、日記はPDB IIで書くだけ。つまり、入力/編集はどちらか一方に限られていて、他方では閲覧するだけなのである。
 見るだけならば、改行がどうなっていようが、さして問題ではない。実際、事始めのネタをAccessから拾っているときも、改行が詰まっている方がかえって一目で見渡せて便利じゃん、とか思っていたほどで。他の形態への出力だの整形してさらに加工するだのが発生しない限り、うっちゃっておいてもなんてことはなかったのだ。

 ほおっておいたもう一つの理由が、PDB(II)で使われている改行コードの指定法がわからなかったから。
 Zaurus(とMac)ではCR、PCではCR+LFが改行コードとして使われている(主にね)、のは、たとえばテキストファイルの扱いなんかでもいつも問題になる話で、特にmabさんが作られるMOREには、そのへん明確に(ユーザにみえやすい形で)意識されているものが多い。
 こういうものは当然ながらばしっと置換してしまえばすむわけで、Access側で処理してしまえばいいことなんだけれど...
 VBAで文字コードを指定するのはChr関数で、CRはChr(13)でLFはChr(10)、それはいいんだけれど、PDB(II)から送られたナカグロってのはChr(13)じゃないのだ。これで検索しても、なぁんも引っ掛からん。

 ここで私は止まってしまった。ナカグロを含む文字列をバイナリエディタで見てみたりもしたんだけれど、16進で見えたってそいつをasciiコードに移す術を知らない私にはどうしようもなくって。
 ま、どのみち支障がないんだからまぁいいや忘れっちゃえ〜い、と思えばずいぶん長いこと、ほったらかしたものである。約2年。なぁんか小骨がはさまったようなというか一点ぽちっと曇りがあるというかどうも不透明なというか、しゃっきりしないものを感じつつも。


 さて先日、まちこみの新着日記からたどり着いたjanetさんのページ。お、"MS-Access2000 との連携"ですか...なに。なになになに。Chr$(31)。そ、そうですかぁ...制御文字範囲の一番けつっぺやんかぁ...

 そぉれがわかれば話は早い。ちょろっと関数作って、とりあえず1レコード1フィールドでテスト...お、できた。
 ということで、以下は実践編。

 でまぁ、必要と思われる方はたいてい既に自前でやってらっしゃることだと思うし、コーディング素人の私が書いたものなんではずかしくもあるのだけれど(だいたいほんとにちょろっとしてるし)、まぁせっかくなんで、作った関数を下に載せる。一度<PRE>タグを使ってみたかったという話もあったりして。janetさんのcooking DB中のコードと、やっていることは同じである。ネタかぶり及び同種コードの掲載を快諾くださったjanetさんに、あらためて感謝。
 まずは、ナカグロをAccessの改行に変える関数。


Public Function CRCrLf(Cont As String) As String

Dim MyPos As Long

MyPos = InStr(Cont, Chr(31))

    Do While MyPos <> 0
        Cont = Left(Cont, MyPos - 1) & Chr(13) & Chr(10) & Mid(Cont, MyPos + 1)
        MyPos = InStr(Cont, Chr(31))
    Loop

CRCrLf = Cont

End Function

 対象が空の場合、InStr関数は0を帰すので、特にその処理は回していない。
 逆にAccessで作ったものをPDB(II)に送る前には、こちらを。当たり前のことながら基本的には、置換対象を取り替えるだけである。
Public Function CrLfCR(Cont As String) As String

Dim MyPos As Long

MyPos = InStr(Cont, Chr(13) & Chr(10))

    Do While MyPos <> 0
        Cont = Left(Cont, MyPos - 1) & Chr(31) & Mid(Cont, MyPos + 2)
        MyPos = InStr(Cont, Chr(13) & Chr(10))
    Loop

CrLfCR = Cont

End Function

 と、ここで終わるのも座りが悪いので、いちおう使い方を。

 まずはMS-Accessで、"モジュール"を"新規作成"。開いたウィンドウに、上述の関数をペたっと貼り付ける。ウィンドウにはあらかじめ2行書かれているはずだけれど、そこはほおっておいて、その下にペたっと。関数二つは、続けて貼ってしまって大丈夫。貼り付けたら、適当な名前でモジュールを保存。

 次に"クエリー"をデザインビューで"新規作成"。"テーブルの追加"画面はなにもせずに閉じてしまって、メニューバー左端のボタンでSQLビューに切り替える。"Select;"の表示に、以下のSQL文を上書きで貼り付け。

UPDATE hogehoge SET hogehoge.field1 = CRCrLf([field1]), hogehoge.field2 = CRCrLf([field2]);
 貼り付けたら、上記"hogehoge"を変換したいDBの名前に、"field1(2)"を変換したいフィールドの名前に、それぞれ書き換える。もっとたくさんのフィールドを処理した場合は、","以降を繰り返す。で、適当な名前でクエリーを保存。

 保存したクエリーを実行すれば、ナカグロがきちんとAccessの改行に変換される。逆をやりたいときは、上記SQLの"CRCrLf"を"CrLfCR"に変えたものを作っておけばいい。
 ただ、対象フィールドが空のレコードがあると、クエリー実行の最後に、そのレコードの数だけ型変換エラーが報告されてしまう。無視して進めれば問題ないんだけれど...

 私は数年分の日記を処理したかったのでごりっと上記の更新クエリーでやってしまうけれど、要はデータを関数に渡せばいいだけなので、そこいらは思いのままである。ちなみにjanetさんのcooking DBでは、フォームにつけたボタンを押すとそのレコードのデータが変換されるようになっている。

 トラブルDBと日記、だけではなくて、最近呑み屋DBとか食い物屋DBとか、TOKさんてかさんが作られたものもいただいているし、そもそもはRozさんあたりが"もっとDBを"ってのを提唱している。Accessがないといかん、というのが苦しいところだけれど、PDB(II)で頑張るよりはやはりPCで作った方が楽には違いないわけで、改行コードの件が解決したからには、ちょいと意欲が増しているところ。

 ということで、もしも(私のように)改行コードで引っ掛かっている方がいらっしゃったら、お試しを。文中、どこか妙なことを言っていたら、是非ご指摘ください。
 しかし、この処理、なんだってパワーリンクに組み込まなかったんだろうなぁ...不思議だ。

(2001/07/14)

(2001/07/14 追記)

 ふと考えてみたら、問題のナカグロをターゲットにしてAsc関数に放り込めば、Chr(31)ってのは苦もなくわかるのであった。たとえばこんな感じ。

Private Sub ShowCode_Click()

Dim Cont As String
Dim Chrcode As Integer

Cont = Me.Field1

Chrcode = Asc(Mid(Cont, xx, 1))

MsgBox Chrcode

End Sub
 ダメダメ甘々ぶりをまたも露呈してしまったわけだけれど、仕方ない、ほんとのことだし。自分としてはこれで、ほんとうにすっきり。ふぅ。

(追記終わり)