2017年01月22日

vbscript:IEを使って64bit環境でJSONをパース

vba/vbscriptでJSONをパースするにはScriptControlを使うのが手っ取り早くていいんだけど、64bit環境だとScriptControlが使えないから困る。何か代わりはないかと思ってたらIEが使えることに気づいた。
※vbscriptで試したけど64bit officeのvbaでも使えると思う。
って書いた後に"HtmlFile"なるものを使うとIEを起動しなくてもHTMLDocumentを使えるということを知ってもっと簡単になった。
Dim doc, jsn
'HTMLDocumentを取得
Set doc = CreateObject("HtmlFile")
'scriptタグを追加
doc.write "<script>document.JsonParse=function (s) {return eval('(' + s + ')');}</script>"
'パース関数でJSONオブジェクトを取得
Set jsn = doc.JsonParse("{a:1,b:2}")
WScript.Echo jsn.b
※ただパースは何も問題ないけど、不思議なことに JSON.stringify を使おうとしたらダメだった。(JSONオブジェクト自体がダメっぽい)

IEを使うパターンは折角書いてたし、こっちは JSON.stringify も使えるからこれはこれで残しとく。
Dim ie, n, jsn
'IEを起動
Set ie = CreateObject("InternetExplorer.Application")
'ie.Visible = True
'空画面を開く
ie.Navigate "about:blank"
Do While ie.Busy Or ie.ReadyState <> 4
WScript.Sleep 100
Loop
ie.document.body.innerHTML = "JsonParse用"
'JSONをパースする関数のscriptタグを動的に作成
Set n = ie.document.createElement("script")
n.Text = "document.JsonParse=function (s) {return eval('(' + s + ')');}"
ie.document.body.appendChild n
'パース関数でJSONオブジェクトを取得
Set jsn = ie.document.JsonParse("{a:1,b:2}")
WScript.Echo jsn.b
'IEを閉じる
ie.Quit
posted by 忘却の達人 at 09:39| Comment(0) | TrackBack(0) | vba | このブログの読者になる | 更新情報をチェックする

2015年03月09日

JavaScript:配列/連想配列のコピー

JSON.parse(JSON.stringify( (連想)配列 ))
posted by 忘却の達人 at 07:51| Comment(1) | TrackBack(0) | JavaScript | このブログの読者になる | 更新情報をチェックする

2015年03月08日

JavaScript:配列/連想配列の要素数の取得

連想配列の要素数を取得するのにいつもfor文回してたけど、Object.keysなるもので要素の配列がとれるらしい。
だからObject.keys( (連想)配列 ).lengthで要素数が取得できる。
配列も通常はlengthで取得するけど、lengthは実際は「添字の最大値 + 1」なので
var arr=[];
arr[0]="A";
arr[1]="B";
arr[9]="C";
なんてイヤらしい配列だと、arr.lengthは 10 を返すので、その場合は Object.keys(arr).length で取得すれば良い。
posted by 忘却の達人 at 21:38| Comment(0) | TrackBack(0) | JavaScript | このブログの読者になる | 更新情報をチェックする

2014年12月16日

vba:砂時計の後始末を考えなくていいクラス

長めの処理でカーソルを砂時計(ブルーリング)にする時、たまにエラー時での後始末を忘れて砂時計のままになってることがあるんだけど、後始末を忘れても勝手にカーソルが元に戻るようにはできないものかと、虫のいいことを考えてたらふと思いついた。
クラスにしてコンストラクタで砂時計、デストラクタで元に戻せば、後始末を忘れても関数を抜ければ勝手にオブジェクトが破棄されてデストラクタが呼ばれるから勝手に元に戻ってくれるじゃないか。

Access用のクラス
クラス名:HourglassOn
Option Compare Database
Option Explicit

Private Sub Class_Initialize()
DoCmd.Hourglass True
End Sub

Private Sub Class_Terminate()
DoCmd.Hourglass False
End Sub
----------------------------------------------
'処理を行う関数
Sub HogeHoge()
On Error GoTo error_proc
With New HourglassOn 'End Withまで砂時計
あれやこれやの処理
End With
MsgBox "終わったぞっ", vbInformation
exit_proc:
Exit Sub
error_proc:
MsgBox Err.Description, vbCritical
Resume exit_proc
End Sub
-----------------------------------------------

この処理は通常は With〜End With の中だけ砂時計になる。但し例外エラーが発生してGoToで With文を抜けた場合は、End Withが実行されていないので砂時計のままとなる。が、それでも関数を抜ければオブジェクトが破棄されるのでちゃんと元のカーソルに戻ってくれるという訳。

砂時計以外でも描画停止・警告非表示などで同じようなやり方ができる。
posted by 忘却の達人 at 22:43| Comment(0) | TrackBack(0) | vba | このブログの読者になる | 更新情報をチェックする

2014年07月26日

Access:レポートをpdfに出力する時はReport_Loadイベントが発生しない

DoCmd.OutputToでpdfに出力した場合に起こる現象。
他のファイル形式で出力する際はちゃんとLoadイベントが発生する。
pdf出力するレポートを作成する際は、Loadイベントを使わないで、Openイベントなどで代替するようにすべし。

Access2010で確認
posted by 忘却の達人 at 11:36| Comment(0) | TrackBack(0) | Access | このブログの読者になる | 更新情報をチェックする

2014年06月07日

Access:リネームして最適化した方がファイルサイズが小さくなる

Access2010で40MBくらいのaccdbで確認した現象。

最適化した時のファイルサイズが段々と増えていってた。開発で常に手を入れてるので、オブジェクトは少しずつ増えていってるわけだけど、経験的にオブジェクトの増加量に比べ、ファイルサイズの増加量が大きすぎるなぁと不思議に思っていた。

ただある時に最適化後のサイズがそれまでより減って、私的にも納得のサイズになっててビックリ。それはテスト環境用にファイルをコピーしてリネームしてから最適化したやつだった。もしかしてと思って、元のファイルもリネームして最適化したら、同じくそれまでより小さくなった。

一応これで問題は解決したわけだけど、そもそもなんでファイル名が最適化に影響してるんだ?(苦笑)
posted by 忘却の達人 at 08:21| Comment(0) | TrackBack(0) | Access | このブログの読者になる | 更新情報をチェックする

2014年02月05日

vba:リボンの最小化

Office2010(2007以降?)で、リボンを最小化・元のサイズに戻す方法。
CommandBars.ExecuteMso "MinimizeRibbon"
このメソッドは最小化と元のサイズをトグルする。

最小化してるかどうかの判定。
CommandBars.GetPressedMso("MinimizeRibbon")
戻り値=True:最小化、False:元のサイズ

リボンを最小化・元のサイズに戻す関数
パラメータのMinimize=True:最小化、False:元のサイズ
Sub MinimizeRibbon(Optional Minimize As Boolean = True)
If Minimize Then
If Not CommandBars.GetPressedMso("MinimizeRibbon") Then
CommandBars.ExecuteMso "MinimizeRibbon"
End If
Else
If CommandBars.GetPressedMso("MinimizeRibbon") Then
CommandBars.ExecuteMso "MinimizeRibbon"
End If
End If
End Sub
posted by 忘却の達人 at 22:53| Comment(0) | TrackBack(0) | vba | このブログの読者になる | 更新情報をチェックする

2013年12月14日

vba:関数内の一部分のみのスコープを持つ変数

もちろんvbaの仕様は変えられないので「変数」では出来ないけど、オブジェクトを使えばWithステートメントの中だけ有効にすることが出来るので、そこに動的にプロパティを追加すればタイトルに近いことが出来る。
具体的にはJavascriptで同じ様なテーマで、連想配列をWithで使う以下の様な方法を書いてたサイトがあったので、これをvbaで実現することにした。
with ({a:0}) {
この中では a は有効。
}
withを抜けると a は参照不可。

そしてvbaで連想配列を返す関数は以下の通り。
Function TempDim(ByVal Dimension As String, Optional Parent As Object) As Object
'Dimension:変数宣言をカンマ区切りの文字列で行う。ex.)"TempNo,Name"
'Parent:ネストする場合、子のWith内では親の連想配列が参照できないので、
' パラメータとして渡す。
Dim sc As Object
Dim hash As Object
Dim i As Long
Dim v() As String
Set sc = CreateObject("ScriptControl")
sc.Language = "JScript"
sc.AddCode "function SetValue(hash, key, value) " & _
"{j=hash ? hash : {};j[key]=value;return j;}"
v = Split(Dimension, ",")
For i = LBound(v) To UBound(v)
Set hash = sc.CodeObject.SetValue(hash, v(i), Null)
Next i
Set hash = sc.CodeObject.SetValue(hash, "Me", hash)
If Not Parent Is Nothing Then
Set hash = sc.CodeObject.SetValue(hash, "Parent", Parent)
End If
Set TempDim = hash
End Function


そして以下の様に使用する。
宣言した名前はプロパティになるので、With内で頭にピリオドを付けて使用する。
With TempDim("i,j")
.i = 1
.j = 1
Do Until .i > 3
Debug.Print "親ループ i="; .i
Debug.Print "親ループ j="; .j
With TempDim("i", .Me) 'Meは自身を参照する
.i = 1
Do Until .i > 3
Debug.Print "子ループ i="; .i
.i = .i + 1
'Parentはパラメータで渡された親の連想配列
.Parent.j = .Parent.j + 1
Loop
End With
.i = .i + 1
Loop
End With

使用上の注意
  • For文のカウンターには使えない。
    For文のカウンターは変数でなければならず、この方法ではオブジェクトのプロパティとなるため使えない。
  • プロパティ名は大文字小文字が区別される。
    JScriptの機能で連想配列を実現してるのでJScriptの制限を受ける。VBエディタの変数名の自動修正機能に注意!
  • Variant型のみ
    連想配列に型が無いためそうなる。あと上の関数では初期値をNULLにしている。
posted by 忘却の達人 at 13:06| Comment(0) | TrackBack(0) | vba | このブログの読者になる | 更新情報をチェックする

2013年09月08日

VBA:IEの画面をキャプチャする手順

ソースは緑里庵のサイトを参照。
gooのトップページをキャプチャした画像。goo.bmp(9.26MB)
1.InternetExplorerオブジェクトを取得
IEを新規に開くか、すでに開いているIEを取得する。
2.IEの表示部分のWindowハンドルを取得
IEのWindowハンドルから子ウインドウをクラス名で辿る。
"Frame Tab" → "TabWindowClass" → "Shell DocObject View"
3.2で取得したWindowハンドルからBitmapを作成
2のWindowハンドルからDCを取得 → 互換DCを作成 → 互換DCの互換Bitmapを作成。作成するBitmapの幅と高さは、document.body.scrollWidth / scrollHeight
4.IEのDCから互換DCへ描画
ドキュメントが1画面に収まらない場合は、描画 → スクロール → 描画 …と繰り返す。
5.Bitmapを保存する
クリップボードにコピーする場合はBitmapハンドルを渡すだけ。
ファイルに作成する場合は、ヘッダーを作成しBitmapをバッファに取得して書き込む。
posted by 忘却の達人 at 09:49| Comment(5) | TrackBack(0) | vba | このブログの読者になる | 更新情報をチェックする

2013年06月18日

Access:長音(ー)を含む文字列をワイルドカードで検索する際の注意(バグ)

テーブルAのメモ欄に、英字1桁数字4桁のコードがあるデータを抽出するSQLを書くと

select * from テーブルA where メモ like "*[A-Z][0-9][0-9][0-9][0-9]*"

こんな感じになるけど、メモが以下のような場合も抽出されてしまう。

今日食べた○×屋のB定食うまかった2013/06/18

どうやら検索条件の「1文字目+適当な文字何文字でも+長音+検索条件の2文字目以降」というパターンまでヒットしてしまうみたい…
長音をハイフンに置換して検索すればとりあえずは対処できるけど、データ量が多いとちと厳しいかも。

Access2003で確認
posted by 忘却の達人 at 22:27| Comment(0) | TrackBack(0) | Access | このブログの読者になる | 更新情報をチェックする

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。