電子書籍の厳選無料作品が豊富!

ExcelVBAなのですが、
InstrB関数で、文字位置のバイト数を取得したいと考えています。

1.文字列[A BCDE] ・・・AとBの間に、半角空白が2つあります。
 ※OKWaveに登録すると半角が1つになってしまうようですが、実際は2つです。
2.文字列[A BCDE] ・・・AとBの間に、全角空白が1つあります。
この文字列に対し、Bの位置は、半角空白2つであっても全角空白1つであっても同じ結果であって欲しかったのですが、
1.の場合:7、2.の場合:5 と結果が返ってきました。

※実際には、文字列から、
  ある記号の次の文字からある記号の前までの文字
 を取り出したいため、その記号の位置を知りたいための処理です。

ヘルプには、
InStrB 関数は検索結果をバイト位置 (先頭からその位置までのバイト数) で返します
とあったので、同じだと思ったのですが・・・

この違いは、なぜ発生するのでしょうか?

ご指導、よろしくお願いします!

A 回答 (4件)

16進定数と16進数はほとんど同義です


VBで扱う場合は &Hをつけます Cなどでは 0xを使います

ChrW(84A5)では 84A5自体を数値として認識できません
Aが入っているので 変数かなとVBは考えますが 84で始まる変数をVBが許容していないで エラーになるでしょう
そこで &Hをつけて これに続く文字列が16進数であると明示します
ChrW(&h84A5) これなら 84 A5 と並んだ 文字を作成できます
VB自体が これが文字として有効なのかどうかはチェックしていません
引数がIntegerで表せる範囲かどうかのチェックする程度のようです
ChrWはもともと文字を生成する関数です
VBが扱う一般的な文字(および文字列)ははUnicodeなのでリファレンスにもUnicode文字を生成すると記述されています
実際には文字列変数の格納先に引数で与えられたデータを与えられた順に格納しています

AscWも同様なことがいえます
文字列のデータのByte順で戻り値を決定します
引数で与えられた 文字列の先頭バイトを下位8ビット、次のデータを上位8ビットとして組み立てた整数(Integer)を返すのです

今回 InStrBでShiftJISでも動作しているのは InStrBの動作が
引数で与えられたデータをバイト順で検索して一致する位置を返すためです
2つの引数の文字体系をあわせてやればどのようなコード体系でも使えます
VBでPrintしたりTextBoxやセルへの代入を行うとそのままでは表示できない場合がありますが

逆にInStrでは失敗しますInStrは文字単位でデータを処理しますのでShiftJISのように 1バイトしかない文字コードは扱えません

> ChrW(&Ha584)とChrW(&H84A5)の両方でテストしましたが、
> 結果は同じでしたが、これはたまたまなのでしょうか?
これは InStrでやったのではありませんか
InStrBならば ChrW(&HA584)は正しい値、ChrW(&H84A5)は0を返すはずです
    • good
    • 0
この回答へのお礼

redfox63様、本当にありがとうございました。
おかげで、おぼろげながらも、大体を理解することができました。
まだ頭に完全にインプットされたわけではありませんが、redfox63様の回答と自分のロジックを照らし合わせて考えればちゃんと納得できるまでには理解できました!
ので、今後のためにもredfox63様の回答をちゃんと保存させていただきました!

> > ChrW(&Ha584)とChrW(&H84A5)の両方でテストしましたが、
> > 結果は同じでしたが、これはたまたまなのでしょうか?
> これは InStrでやったのではありませんか
> InStrBならば ChrW(&HA584)は正しい値、ChrW(&H84A5)は0を返すはずです
 →その通りでした、先日テストした式が残っていないので(VBAのイミティエイトウィンドウでテストしていたので・・・)、どういう式でテストしたのか確実ではないのですが、本日InstrBでテストしたところ、ChrW(&HA584)は正しい位置情報、ChrW(&H84A5)の場合は0が返ってきました。

本当に助かりました。また、いつも文字コードをあやふやにしていたのですが、redfox63様のおかげで今度からは理解しながら記述できると思います。

本当にありがとうございました!

お礼日時:2008/11/17 20:55

罫線素辺などを検索したいのであれば


AscW(StrConv( "├", vbFromUnicode) )
を使わないといけないでしょう

AscBでは取得した下位8ビットしか返さないでしょうから
半角文字なら AscBでいいと思います

> AscB("├")で得た数値が28だったので
では Unicodeの下位8ビットの取得になります

InStrB( StrConv( "├", vbFromUnicode), ChrW( &Ha584) )
といった具合になります
本来├ のShiftJISコードは&H84A5なのですが インテルCPUでは 上位8ビットと下位8ビットが入れ替わりますので &HA584 を与えます

この回答への補足

今回のモジュールは、
  Dim str_w As String
  Dim wk As Integer
  Dim lng_Code As Long

  str_w = ActiveSheet.Cells(1, "A").Value
  lng_Code = AscW(StrConv("├", vbFromUnicode))
  wk = InStrB(StrConv(str_w, vbFromUnicode), ChrW(lng_Code))
  If wk = 0 Then
    lng_Code = AscW(StrConv("└", vbFromUnicode))
    wk = InStrB(StrConv(str_w, vbFromUnicode), ChrW(lng_Code))
  End If
  msgbox wk
というふうに、
まず、セルの値が入ってくる str_w の中から、"├"のバイト位置("├"がなければ"└"のバイト位置)を調べたい、というものだったのですが、
1.├や└などの全角文字は、Unicodeでは16ビットで表す
2.ヘルプより:「AscB 関数は、最初の文字の文字コードではなく、最初のバイト データを返します。AscW 関数は、Unicode 文字セットの文字を返します。」
  ・・・AscBは、最初のバイトデータ(1バイト=8ビット)を返す、ということは、16ビットのうちの8ビットしか取得できないから、AscWを使う
3.AscWを使うから、ChrWを使う
ということで、間違ってませんか?

そして、これは質問なのですが、
1.WEBでUnicodeのコード表を見てみたところ、"├"は、Shift-Jisコードは"84A5"でした。
CharW(&H84A5) の"&H"はなんだろう?と思い、調べたら、「16進定数」だそうですが、これはただの16進とは何が違うのでしょうか?
ChrW(84A5)で試したら、確かに正常には検索されませんでした。
2.ChrW(&Ha584)とChrW(&H84A5)の両方でテストしましたが、結果は同じでしたが、これはたまたまなのでしょうか?
3.今回は、実際は、AscW(StrConv("├", vbFromUnicode))で返ってきた数値を使ってChrW(数値)としましたが、これでも問題はないのでしょうか?(処理は動きました)
4.ヘルプより:「AscW 関数は、Unicode 文字セットの文字を返します。」
「ChrW 関数は、Unicode 文字セットの文字を含む文字列型 (String) で文字を返します。」
 ・・・ですが、ChaW()でShiftJISコードを入れても動くのはなぜ?

本当に、本当にすみません。
どうかよろしくお願いします。

補足日時:2008/11/14 21:10
    • good
    • 0
この回答へのお礼

redfox63様、何度も的確なご指導、本当にありがとうございます!
おかげさまで、処理できました!本当にありがとうございます。

ただ、すみません、せっかくご指導いただいているのに理解ができず、教えていただいた通り記述しただけで正常にできてしまったのですが、redfox63様がよろしければ、"文字コード"について、もう少し教えていただけないでしょうか?

本当にすみません、せっかく教えていただいたので、正しく理解したくて・・・
お時間があるときで構いませんので、またご指導いただけないでしょうか?

質問文が長くなったので、補足に記述します。
どうか、よろしくお願いいたします。

お礼日時:2008/11/14 21:07

お求めのものはAscBでしょうか ・・・

    • good
    • 0
この回答へのお礼

redfox63様、再度ご回答ありがとうございます。

AscB、その通りのようです!
ですが・・・
実際の記号でテストしたところ、正常に動かなかったのです。

実際の記号は、"├"なのですが、
AscB("├")で得た数値が28だったので、
InStrB(StrConv("├", vbFromUnicode), ChrB(28))
として試してみたのですが、結果0で返ってきてしまいました・・・

「文字コード」について、知識が乏しいので、継続して調べていますが、ご指導いただけますでしょうか?

よろしくお願いいたします。

お礼日時:2008/11/13 20:47

VBAが内部で保持する文字列は Unicodeになっているためです



dim b1() as byte, b2() byte, ss as string
ss = "A__BCDE" ' _ は半角スペース
b1 = ss
ss = "A BCDE" ' AB間は全角スペース
b2 = ss
とした場合
b1は 65 0 32 0 32 0 66 0 67 0 68 0 69 0
b2は 65 0 0 48 66 0 67 0 68 0 69 0
といった具合になります
66 0 のある位置は b1は7番目 b2は5番目になります

Shift_JIS文字列で調べるならば
InStrB( StrConv( ss, vbFromUnicode), ChrB(66))
ならば どちらも 4が返ってきます
    • good
    • 0
この回答へのお礼

すばやい回答、ありがとうございます!

そのものズバリ!の回答でした!ありがとうございます!

便乗してお聞きしたいのですが、
「ある記号」というのがいろいろあるのですが、
ChrB()で指定する文字コードを確認する関数、ってあるものなのでしょうか?

お礼日時:2008/11/12 23:51

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