##目的
Excel VBAからpost経由でGASに日本語を送りつけたい。
転送データは最終的にスプレッドシートに保存する。
##対応
- Excel VBA(Shift-JIS)
- COM経由でDLL呼び出し(UTF-16に変換、コードユニットに変換する)
- POSTする
- GASで受け取ったコードユニットを文字列変換
- スプシに書き込み
##詳細
GASのREST APIを使ってpostできるが、英数字のみ送信可能。
BASE64とか使えよって話なんだけどね。
Excel VBAから送る要件があったのと、GAS側であまり処理時間かけたくなかったので簡易的な実装を行った。
VBAから直接日本語を送ると、Shift-JISなのでGAS側で文字として扱えない。
そこでGAS(というよりもJSの内部表現の話)で使っているUTF-16に変換する必要がある。
VBAでは.Netの処理がフルに使えないので、C#でサクっと作成。
###C#側
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace CCC
{
[ComVisible(true)]
public interface ICCC
{
[Description("文字列をユニコード表記に変換する")]
string ConvertUnicodeCode(string target);
}
[ClassInterface(ClassInterfaceType.None)]
public class CCC:ICCC
{
public string ConvertUnicodeCode(string target)
{
String str = target;
if (str == null)
{
Console.Write("input arg. ex) ccc.exe \"No problem. Everything's fine.\"");
return "none";
}
string retStr = "";
char[] chars = str.ToCharArray();
foreach (char c in chars)
{
retStr += String.Format("{0:x4}", (int)c);
}
return retStr;
}
}
}
intにキャストするだけでコードユニットとれるって便利。
参考にした記事
注意点は
・インターフェースを実装する事
・[できたライブラリを64bitなのか32bitかで合わせてレジストリに登録する事]
(https://qiita.com/aoi_erimiya/items/aa9160017660b1830891)
###VBA側
'パラメータ
Dim str_Parameter As String
str_Parameter = POST_CSV_Convert(str_SheetName)
'文字コードをUnicodeコード表記に変換
Application.StatusBar = "送信情報をエンコードしています..."
Dim cuc As New CCC.CCC
Dim encodeDat As String
encodeDat = "data=" & cuc.ConvertUnicodeCode(str_Parameter)
'--------------
'POST実行
'--------------
DoEvents
Dim xmlhttp As Object
Set xmlhttp = CreateObject("msxml2.xmlhttp")
xmlhttp.Open "POST", url, False
xmlhttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
xmlhttp.send (encodeDat)
登録したDLLを呼び出して使う。
注意点は
postのパラメータ名(data=とか)の部分は変換しない。
GASで受け取れなくなるので。
###GAS側
function codeConvert(charCodeStr) {
uniString = [];
var idx = 0;
while(idx < charCodeStr.length){
var sliceChar = String.fromCharCode("0x" + charCodeStr.slice(idx, idx + 4))
uniString.push(sliceChar);
idx = idx + 4;
}
return uniString.join('');
}
function doPost(e) {
var paramData = '' + e.parameters.data;
var datas = codeConvert(paramData).split(':');
// スプシに書き込みとか
}
受け取ったコードユニットを4文字毎に切り出して、String.fromCharCode()を使う。
##課題
日本語のやり取りはできるようになったけど、どうしても転送量が増えてしまう。
一回で済んでたところを、分割して送信せなあかん場合もある。
zipかなにかしてやりたい。
あとは、コードユニットに変換しただけでほぼ平文なので、重要な情報を扱う際には何かしら暗号化もしてあげればよいかなーと思う。