プロが教える店舗&オフィスのセキュリティ対策術

Access97でクエリ内で文字の長さを判定しようとして
いたのですが、Strconv関数の妙な挙動に戸惑っています。

barというテキスト型のフィールドをもつfooという
テーブルを定義して、"1","22","333","4444"という
4つのレコードを作成します。

そして下記のようなクエリを作成し実行します。
SELECT foo.bar, LenB(StrConv([foo].[bar],128)) AS 式1, StrConv(StrConv([foo].[bar],128),64) AS 式2
FROM foo;

すると、結果は下記のようになってしまいます。

bar |式1|式2
------------
1 | 0|
22 | 2|22
333 | 2|?
4444| 4|?

式1は奇数Byteの結果が、式2は"22"以外の結果が
正しくありません。

このようになってしまう理由と、対処方法を教えて
ください。

環境は Windows2000ProSP4, Access97SR2 です。

ちなみにAccess2000で実行すると、正しい結果が
表示されます。

A 回答 (2件)

a = 1


ab = 2
abc = 3
あ = 2
あい = 4
あいう = 6
という結果をクエリでも VBA でも受け取れるようにしたい、ということですね?

Access 95 以降は VBA が実装されましたが、VBA 内部では文字を Unicode で扱っています。
しかし Access 95/97 の表の部分では文字を ANSI で扱っているため、非常にやっかいです。
Access 2000 以降では全て Unicode になっています。
-------------------------------------------
ちなみに Access 97 でテキスト型フィールドのサイズをめいっぱいの255にしたとして、全角だと127文字、半角だと256文字までの制限になります。
これはこのバージョンの Access が半角文字を1byte、全角文字を2byteで管理しているからです。
Access 2000 以降は全角も半角も256文字入りますので、Unicode で格納していることがわかります。
-------------------------------------------

で、Access 97 でも 2000 以降でも使える LenBEx 関数を作ってみましたので試してみてください。
標準モジュールに下記コードを入力して、クエリの式ビルダからも関数の一覧で選択すれば使用できます。

Public Function LenBEx(var As Variant) As Variant
  LenBEx = LenB(StrConv(var, vbFromUnicode))
End Function
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

> Access 95 以降は VBA が実装されましたが、
> VBA 内部では文字を Unicode で扱っています。
> しかし Access 95/97 の表の部分では文字を
> ANSI で扱っているため、非常にやっかいです。

VBAとテーブルでコードが異なっているというのは
恥ずかしながら初めて知りました。

不思議でもなんでもなくて、そういうものだったのですね。
勉強になりました。

お礼日時:2004/12/22 15:29

原因は Unicode ですね。


Access 97 は Unicode じゃないです。

実際にどういう結果を期待しているのかがわからないので適当に書きます。適宜試してみてください。

SELECT foo.bar, LenB(StrConv(StrConv([foo].[bar],64),128)) As 式1
FROM foo;

StrConv の 64 は「規定のコードページから Unicode への変換」なので、Access 97 では ANSI から Unicode へ明示的に変更した上で、さらに StrConv の 128 で Unicode から規定のコードページ ANSI に変換します。
その結果を LenB に掛けていますので、
bar | 式1
1 | 2
22 | 4
333 | 6
4444 | 8
になります。
Access 2000 以降で行っても同様の結果となります。
LenB = バイト数 なので、半角1文字 = 2byte です。
LenB を Len にすれば 式1 の結果は「見た目の文字数」となります。

ポイントとしては、まず最初に「規定のページコード」から明示的に Unicode に統一する。
ってところでしょうか。

この回答への補足

ご回答ありがとうございます。

>実際にどういう結果を期待しているのかがわからないので

半角文字は1Byte,全角文字は2Byteとして、
Byte数を取りたいのです。

ご回答いただいた

> LenB(StrConv(StrConv([foo].[bar],64),128))

と、LenB([foo].[bar])の違いがわかりません。
どちらも結果は全角、半角ともに一文字に対して
2を返します。
全角、半角ともに一文字2Byteということは、その状態が
Unicodeなのではないか、という理解をしていました。
なので、vbFromUnicode(128)を使用して変換をかけて
からByte数を取得しようとしたわけです。

ちなみに、不思議なのはクエリでなくVBA上では私の
意図したとおり動作することです。

補足日時:2004/12/22 11:03
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!