怠日記

写真・金魚・昆虫・プログラミングの趣味を語るサイトです。似たようなことをnoteにも書いたり書いてなかったり。

VBA: Unicodeのiniファイルに書き込むには | WritePrivateProfileStringW関数

VBA で ANSI の ini ファイルに書き込む方法は以下のページに書いたとおり。

nmk365.hatenablog.jp

それと同様に Unicode の ini ファイルに文字列を書き込むには、Win32API の WritePrivateProfileStringW 関数を使う。

サンプルコード

以下に WritePrivateProfileStringW 関数を使った書き込みのサンプルを示す。

Option Explicit

Private Declare PtrSafe Function WritePrivateProfileStringW Lib "kernel32" ( _
    ByVal lpAppName As LongPtr, _
    ByVal lpKeyName As LongPtr, _
    ByVal lpString As LongPtr, _
    ByVal lpFileName As LongPtr _
) As Long

Public Sub Main()

    'マクロブックと同じ場所の app.ini ファイルを対象とする
    Dim iniFilePath As String
    iniFilePath = ThisWorkbook.Path & "\app.ini"

    '値を書き込む
    '  関数の戻り値は正常終了なら0以外、異常終了なら0となる。
    Dim ret As Long
    ret = WritePrivateProfileStringW(StrPtr("TestSection"), _
                                     StrPtr("TestKey"), _
                                     StrPtr("書き込みテスト" & ChrW$(9825)), _
                                     StrPtr(iniFilePath))

    If ret = 0 Then
        Debug.Print "書き込み失敗"
    Else
        Debug.Print "書き込み成功"
    End If

End Sub

事前準備としてマクロを実行する前に、マクロブックと同じ場所に以下のような内容で app.ini ファイルを作っておく。
文字コードは Unicode(UTF-16 LE)にしておくこと。

; iniファイルテスト
[TestSection]
TestKey=設定値

マクロを実行すると TestSection セクションの TestKey キーに「書き込みテスト♡」が設定される。
「♡」は Unicode 文字だが問題なく書き込まれている。

; iniファイルテスト
[TestSection]
TestKey=書き込みテスト♡

もし app.ini ファイルがなかったり、ファイルの文字コードが Unicode でなかったりすると、ANSI 文字が書き込まれる。
Unicode 文字の「♡」は ? になっている。

[TestSection]
TestKey=書き込みテスト?

解説

WritePrivateProfileStringW 関数は次のように定義されている。

BOOL WritePrivateProfileStringW(
  [in] LPCWSTR lpAppName,
  [in] LPCWSTR lpKeyName,
  [in] LPCWSTR lpString,
  [in] LPCWSTR lpFileName
);

データ型の LPCWSTR は Unicode 文字列を表す。

VBA から LPCWSTR に Unicode 文字列を渡すためには、文字列のポインタを渡すようにしなければならない。

よって WritePrivateProfileStringW を VBA の宣言セクションで宣言するときは、データ型を LongPtr にする。
ここを LongPtr ではなく String にしてしまうと正しく動かないので注意してほしい。

Private Declare PtrSafe Function WritePrivateProfileStringW Lib "kernel32" ( _
    ByVal lpAppName As LongPtr, _
    ByVal lpKeyName As LongPtr, _
    ByVal lpString As LongPtr, _
    ByVal lpFileName As LongPtr _
) As Long


WritePrivateProfileStringW 関数は以下のように呼び出す。

StrPtr 関数を使って、VBA の文字列のポインタを引数に渡すのがポイントである。

ret = WritePrivateProfileStringW(StrPtr("TestSection"), _
                                 StrPtr("TestKey"), _
                                 StrPtr("書き込みテスト" & ChrW$(9825)), _
                                 StrPtr(iniFilePath))

戻り値は、書き込みができたら 0 以外、できなかったら 0 になる。


実は WritePrivateProfileStringW 関数は ANSI と Unicode のどちらにも対応している。
どちらを対象とするかは、引数 lpFileName の指定によって決まるらしい。

リファレンスには次のように書かれている。

[in] lpFileName

初期化ファイルの名前。

ファイルが既に存在し、Unicode 文字で構成されている場合、この関数は Unicode 文字をファイルに書き込みます。 それ以外の場合、関数は ANSI 文字を書き込みます。

要は Unicode の ini ファイルがあれば Unicode、それ以外なら ANSI となるようだ。