Excel (VBA)

Excel VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 10 Pro : Excel 2013)
StrConv(xxxx, vbUnicode) の変換について
投稿日時: 19/12/13 15:34:25
投稿者: アブサン

お世話になります。
 
StrConv(xxxx, vbUnicode) の変換が思った通りにいかず
質問させていただきます。
 
◆やりたいこと
  自作DLLを呼び出したいのですが、
  Excelファイルがあるフォルダ内に「bin」フォルダを置き
  その中にDLLファイルを配置しています。
 
  パスが通っていない場所のため
  SetDefaultDllDirectories と AddDllDirectory を
  使用して検索パスの追加を行っています。
 
  具体的には下記のようにしています。
 
  Dim path As String
  path = ThisWorkbook.Path & "\bin"
  path = StrConv(path, vbUnicode, 1041)
  SetDefaultDllDirectories (&H1000)
  Call AddDllDirectory(path)
 
  AddDllDirectory の引数が PCWSTR のため
  StrConv で Unicode変換しております。
 
◆うまくいかないこと
  DLLファイルのパスに全角カナの小さい「ョ」が入っていると
  DLLファイルが認識されませんでした。
  「ョ」を大きい「ア」に変えると認識します。
 
  試しに下記のようにしてUnicode変換されたパスを戻してみると
  「ョ」が「?」に化けます。「ア」の場合は化けません。
 
    path = StrConv(path, vbUnicode, 1041)
    path = StrConv(path, vbFromUnicode, 1041)
 
  Unicode変換が思った通りに変換できていないことが原因と
  判断しました。
 
ググってみたのですが、原因がわかりません。
何かアドバイスをいただけると助かります。

回答
投稿日時: 19/12/13 18:00:16
投稿者: sk

引用:
Dim path As String
  path = ThisWorkbook.Path & "\bin"
  path = StrConv(path, vbUnicode, 1041)
  SetDefaultDllDirectories (&H1000)
  Call AddDllDirectory(path)

そのステートメント自体が不要なのでは。
 
引用:
試しに下記のようにしてUnicode変換されたパスを戻してみると
「ョ」が「?」に化けます。「ア」の場合は化けません。
 
   path = StrConv(path, vbUnicode, 1041)
   path = StrConv(path, vbFromUnicode, 1041)

-----------------------------------------------
Private Sub Test1()
     
    Dim ws As Excel.Worksheet
    Dim Path As String
     
    Set ws = Workbooks.Add.Worksheets(1)
     
    With ws
        Path = "ョ"
        .Cells(1, 1) = Path
        Path = StrConv(Path, vbFromUnicode)
        .Cells(2, 1) = Path
        Path = StrConv(Path, vbUnicode)
        .Cells(3, 1) = Path
     
        Path = "ョ"
        .Cells(1, 2) = Path
        Path = StrConv(Path, vbUnicode)
        .Cells(2, 2) = Path
        Path = StrConv(Path, vbFromUnicode)
        .Cells(3, 2) = Path
     
    End With
     
    Set ws = Nothing
 
End Sub
-----------------------------------------------
 
とりあえず、以上のコードの実行結果をご確認下さい。

回答
投稿日時: 19/12/14 15:22:28
投稿者: MMYS

VBAの内部文字コードはご存知ですか。
またAPI呼び出し方が、
・ANSI版
・Unicode版
で記述が異なります。そのあたりは、大丈夫ですか。
Net上のサンプルは多くがANSI版です。

回答
投稿日時: 19/12/16 09:10:21
投稿者: simple

>AddDllDirectory の引数が PCWSTR のため
>StrConv で Unicode変換しております。
そうした対応が必要なのは、
コードで直接、""に入れた文字列を直書きしたときじゃないですか?

回答
投稿日時: 19/12/16 13:42:23
投稿者: よろずや

simple さんの引用:
>AddDllDirectory の引数が PCWSTR のため
>StrConv で Unicode変換しております。
そうした対応が必要なのは、
コードで直接、""に入れた文字列を直書きしたときじゃないですか?

VBE の画面上は SJISコード ですが、VBA の内部では Unicode で動いています。

回答
投稿日時: 19/12/16 15:27:50
投稿者: simple

ありがとうございます。
文字化けの議論でそれは知っていましたが
変な回路の繋がりになっていました。
失礼。黒歴史ですね。

投稿日時: 19/12/16 18:56:16
投稿者: アブサン

sk様、ご返答いただきありがとうございます。
 

引用:
引用:

Dim path As String
path = ThisWorkbook.Path & "\bin"
path = StrConv(path, vbUnicode, 1041)
SetDefaultDllDirectories (&H1000)
Call AddDllDirectory(path)

そのステートメント自体が不要なのでは。

「ョ」などのNGな文字を含まないパスでは
StrConvせずに渡すとDLLファイルが認識されず
StrConvすると認識される状況です。
 
引用:
とりあえず、以上のコードの実行結果をご確認下さい。

コードの実行結果をご報告いたします。
 
'↓「ョ」がでます
Path = "ョ"
.Cells(1, 1) = Path
 
'↓漢字1文字がでますが機種依存のためWebで表記できません
Path = StrConv(Path, vbFromUnicode)
.Cells(2, 1) = Path
 
'↓「ョ」がでます
Path = StrConv(Path, vbUnicode)
.Cells(3, 1) = Path
 
'↓「ョ」がでます
Path = "ョ"
.Cells(1, 2) = Path
 
'↓「・」がでます
Path = StrConv(Path, vbUnicode)
.Cells(2, 2) = Path
 
'↓漢字1文字がでますが機種依存のためWebで表記できません
Path = StrConv(Path, vbFromUnicode)
.Cells(3, 2) = Path
[/quote]
 
よろしくお願いいたします。

回答
投稿日時: 19/12/16 19:25:30
投稿者: よろずや

API呼び出し時には String型の中身は自動的にS-JISに変換される
 
https://software.opensquare.net/relaxtools/archives/3400/

投稿日時: 19/12/16 19:28:35
投稿者: アブサン

MMYS様、simple様、よろず様 ご返答いただきありがとうございます。
 

引用:
VBAの内部文字コードはご存知ですか。
またAPI呼び出し方が、
・ANSI版
・Unicode版
で記述が異なります。そのあたりは、大丈夫ですか。

大丈夫ではないかもしれません(*_*;
 
まず、AddDllDirectoryを調べなおしました。
Win32ApiにはANSI版のAとUnicode版のWがあるということですが
AddDllDirectoryは1つしかないようです。
 
次にうまくいく文字(とりあえず「ア」)がどのように
なっているのか確認してみました。
 
 
下記コードでウォッチでbDataの末尾2バイトを確認すると
162(0xA2)、48(0x30)となっています。
 
UTF-16のコード表をググって確認したところ
16進数で30A2は「ア」になっていました。
バイト順が逆なのはリトルエンディアンということかなぁ。
 
特にStrConvで変換せずともUTF-16ということがわかりました。
 
-----------------------------------------------
Dim Path As String
Dim bData() As Byte
 
Path = ThisWorkbook.Path 'C:\xxxx\ア
bData = Path
-----------------------------------------------
 
今度は下記でStrConvした結果がどうなるか見てみました。
どうも1文字4バイトで戻っているようです。
(そう判断した理由はその前のコードがエンサインとなりますが
92(0x5C)、0、0、0 となっていたからです。)
末尾4バイトは下記になります。
 
98(0x62)、255(0xFF)、48(0x30)、0
 
これがどういう値かよくわかりませんが
この状態でDLLは認識されています。
 
-----------------------------------------------
Path = ThisWorkbook.Path 'C:\xxxx\ア
bData = StrConv(Path, vbUnicode, 1041)
-----------------------------------------------
 
PCWSTRにはUTF-16を渡せばよいのかと思っていたのですが
よくわからなくなりました。
お分かりになるようでしたらお教えいただけると助かります <(_ _)>

投稿日時: 19/12/16 19:30:15
投稿者: アブサン

よろずや様、ご返答ありがとうございます。
 
すいません。入れ違いになりました。
確認してみます。

投稿日時: 19/12/16 19:42:00
投稿者: アブサン

よろずや様にお教えいただいたサイトを参考にして解決いたしました。
修正した結果、下記のようになりました。
 
Private Declare PtrSafe Function SetDefaultDllDirectories Lib "kernel32.dll" ( _
    ByVal DirectoryFlags As Long) As Long
 
Private Declare PtrSafe Function AddDllDirectory Lib "kernel32.dll" ( _
    ByVal fileName As LongPtr) As LongPtr
 
Sub Test()
    Dim Path As String
     
    Path = ThisWorkbook.Path & "\bin"
    SetDefaultDllDirectories (&H1000) 'LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
    Call AddDllDirectory(StrPtr(Path))
End Sub
 
ご回答してくださった皆様に感謝いたします。
ありがとうございました <(_ _)>