[ 新規に投稿する ]

Scripting.Dictionaryのsetpropnum,setpropstrの問題についてNo.10502
ラフ さん 24/12/24 17:58 [ コメントを投稿する ]
  Scripting.Dictionaryのsetpropnum,setpropstrの問題について

今までaddメソッドで追加して取得しかしてこなかったので気づきませんでしたが、
秀丸メールの方で後で値を変更する必要が生じたのでsetpropxxxを使いましたが上手く値が変わらない。
でテストプロ作って検証した結果

Itemプロパティの解釈を間違えているように思える。

Microsoftのページでは
構文
オブジェクト.Item(key) [ = newitem ]
となっていて、= newitemが有る場合が設定、無い場合が取得になります。

VBScriptで書くと値を設定する時のItemプロパティは
(1) objHash,Item(key) = val
または
(2) objHash(key) = val
と書きます。

これを秀丸マクロで書くと
(1) setpropstr #objHash, "Item", $key, $value;
(1) setpropnum #objHash, "Item", $key, #value;
または
(2) setpropstr #objHash, $key, $value;
(2) setpropnum #objHash, $key, #value;
になると思います。
(2)は上記MSのページの構文外なのでVBScript固有かもしれないということでサポートしなくていいと思いますが、

(1)がうまく働いていないです。
まずsetpropstr ですが値が変わらない。getresultex(10)がfalseを返し
getresultex(11)の値が0x8002000Eになります。
「DISP_E_BADPARAMCOUNT 0x8002000E パラメーターの数が無効です。」

次にsetpropnum ですが、マクロエラー:数値が指定されるべき所に数値以外のものが指定されています。
となります。


==環境==
[Windows]
エディション:Windows 10 Pro 64bit
バージョン:22H2
OSビルド:19045.5247

[秀丸エディタ]
バージョン:9.39 64bit

以上調査よろしくお願いします。
[ ]
RE:10502 Scripting.Dictionaryのsetpropnum,setpropstrの問No.10503
こみやんま さん 24/12/25 00:45 [ コメントを投稿する ]
  これって一般的にいうところの、

オブジェクト.プロパティ = 値

秀丸が想定しているうのは、

obj.prop1 = "あいう"; 
obj.prop2 = 3;

とか

var a = obj.prop1;

といった形であって、

obj.prop1("key1") = "あいう";
obj.prop2("key2") = 3;

などではないということだからかと。

というか一般的に、

obj.prop1["key1"] = "あいう";
obj.prop2["key1"] = 3;

というのはあっても

obj.prop1("key1") = "あいう";

っていうのは一般的には結構「『呼び出し評価』の結果自体が代入先を参照しているっていうのは行儀が悪いよね、それ」っていう感じなので
ほとんど採用されないですよね...

秀丸のJSで言えば、

js {

var a = createobject("Scripting.Dictionary");

debuginfo(2);

a.Add("かきく", "りんご");
a.Add("あいう", "aaa");
a.Add("あああ", 3);

console.log(a.Item("かきく"));
console.log(a.Item("あああ"));

a.Item("ううう") = "かきく";
// え〜 インデクサ(=[ ])じゃなくて、呼び出し評価=( )で代入先(への参照)が返ってくるんか〜 的な。

// インデクサでないなら普通のセンスなら
// a.Item("ううう", "かきく"); という実装であるのが普通なんだけど、そうはなっていない。

console.log(a.Item("ううう"));

// jsmodeではなく、「素の秀丸マクロ」でやるなら、該当のキーがあるということ前提で、
// 以下みたいなことを「秀丸マクロのmember」等でやる方が簡単なんじゃないでしょうか?
if (a.Exists("ううう")) {
  a.Remove("ううう");
  a.Add("ううう", 100);
  console.log(a.Item("ううう"));
}


}


[ ]
RE:10502 Scripting.Dictionaryのsetpropnum,setpropstrの問題No.10504
秀丸担当 さん 24/12/25 10:35 [ コメントを投稿する ]
  setpropstrやsetpropnumは、引数付きのプロパティ設定には対応していませんでした。
COMオブジェクトの扱いは、これまでは秀丸マクロの文法に合わせるため、非常に面倒でした。
今はJavaScriptが扱えるようになり、扱いやすくなっています。
従来マクロの方式をこれ以上拡張するのは限界があるので、引数付きのプロパティ設定をする場合はJavaScriptを使ってほしいです。

ただ今回の場合は別の面倒な問題もありました。
Scripting.DictionaryのKeysやItemsはほぼvbs用(?)の、SafeArrayというものになっていて、JavaScriptではそのままでは扱えず、toArray()でJavaScriptの配列に変換してやる必要がありました。

マクロヘルプの、
目次− COMの呼び出し− SafeArrayの返り値について 
のところに、従来マクロの例があります。
これを、jsに書きなおすと以下のようにしてできました。(それと引数付きプロパティ設定も)

newfile;
js{
    objDic = createobject("Scripting.Dictionary");
    objDic.add( "Key1", "Value1" );
    objDic.add( "Key2", 2 );
    objDic.add( 3, "Value3" );
    objDic.Item("Key4") = 4 ;//new!
    objDic.Item("Key5") = "Value5" ;//new!
    
    objKeys = objDic.Keys().toArray();//SafeArrayをjsの配列に
    c = objKeys.length;//objKeys.Count;ではなくjsの配列
    i = 0;
    insert( "Keys:"+c+"\n" );
    while(i<c){
        key = objKeys[i];//Itemではなくjsの配列になっている
        if(key){
            insert( "[\""+key+"\"]=" );
            a = objDic.Item(key);
            if(a){
                insert( "\""+a+"\"" );
            } else {
                a = objDic.Item(key);
                if(a){
                    insert(a);
                }
            }
            insert("\n");
            i++;
            continue;
        }
        key = objKeys.Item(i);
        if(key){
            insert( "["+key+"]=");
            a = objDic.Item(key);
            if(a){
                insert( "\""+a+"\"");
            } else {
                a = objDic.Item(key);
                if(a){
                    insert(a);
                }
            }
            insert("\n");
            i++;
            continue;
        }
        i++;
    }
}
endmacro;

----------------------

さらには、そもそもJavaScriptの{}のオブジェクトはハッシュなので、これをそのまんま使うと非常に簡潔に書くことができます。


//JScriptでも通るfor(...in...)
js{
    objDic={};//オブジェクト=ハッシュ
    objDic.Key1="Value1";
    objDic.Key2=2;
    objDic[3]= "Value3";
    objDic["Key4"] = 4 ; //KeyX=でも、["KeyX"]=でもいける
    objDic["Key5"] = "Value5" ;
    
    //個数はc=0;for( key in objDic) {c++;}だけど必要ない
    for( key in objDic) {
        insert( "[\""+key+"\"]=" +objDic[key]+"\n" );
    }
}
endmacro;


//配列でやる場合はWebView2が必要
jsmode "WebView2";
js{
    objDic={};//オブジェクト=ハッシュ
    objDic.Key1="Value1";
    objDic.Key2=2;
    objDic[3]= "Value3";
    objDic["Key4"] = 4 ; //KeyX=でも、["KeyX"]=でもいける
    objDic["Key5"] = "Value5" ;
    
    keys=Object.keys(objDic);//この文法はWebView2が必要
    insert("Keys:"+keys.length+"\n");
    for( i=0;i<keys.length;i++) {
        insert( "[\""+keys[i]+"\"]=" +objDic[keys[i]]+"\n" );
    }
}
endmacro;


このあたりもヘルプに書いておこうと思います。
[ ]
RE:10504 Scripting.Dictionaryのsetpropnum,setpropstrの問題No.10505
秀丸担当 さん 24/12/25 10:43 [ コメントを投稿する ]
  すみません、whileループ後半の
key = objKeys.Item(i);
の次のブロックは必要なかったです。
[ ]
RE:10503 Scripting.Dictionaryのsetpropnum,setpropstrの問No.10508
ラフ さん 24/12/27 20:17 [ コメントを投稿する ]
  >if (a.Exists("ううう")) {
>  a.Remove("ううう");
>  a.Add("ううう", 100);
>  console.log(a.Item("ううう"));
>}
この方式は真っ先に考えましたが、ループの中の処理でその回数分やるのがちょっと嫌だったので不採用にしてます。
[ ]
RE:10504 Scripting.Dictionaryのsetpropnum,setpropstrの問題No.10509
ラフ さん 24/12/27 20:19 [ コメントを投稿する ]
  Javascriptの方がハッシュを扱いやすいのは重々承知の上です。
私の書くスクリプトの70%から80%はJavascriptです(tampermonkey用ですが)。
残り20%から30%が秀丸ファイラーのVBScript、エクセルのVBA、秀丸マクロという感じです。
今回は秀丸メール用のマクロを書いていて、たまたま値を変更したかっただけで、ハッシュがメインではありません。
全てjavascriptで書けばいいんでしょうが、既にDictionaryの値変更以外の部分が完成しているので今更1800行ものマクロを書き直すわけにもいきません。

ということで、今回はロジックを少しだけ変更して、アカウントリストを取得してiniファイルに保存する際に、アカウントグループ別アカウント数を同時に記録しておいて、それを読むことにしました。
[ ]

[ 新規に投稿する ]