2014年10月25日土曜日

[VBA] ネットワーク ドライブであることを確認する

VBAで、ディスクがネットワーク ドライブであることを確認する方法です

Windows Script Host の EnumNetworkDrives メソッドで、ネットワークドライブのコレクションを得られます。調査したいドライブ名がこのコレクションに含まれていれば、ネットワークドライブです。ローカル ドライブはこのコレクションには含まれません。

今PCが接続しているネットワークドライブの一覧は、コマンドプロンプトから
> net use
で確認できます。EnumNetworkDrives のコレクションはこれと同じ内容になっています。

■ サンプルロジック
' 参照設定:Windows Script Host Object Model
Dim Network As New WshNetwork
Dim Drives As IWshCollection
Set Drives = Network.EnumNetworkDrives

Dim i As Integer
For i = 0 To Drives.Length - 1 Step 2
    ' コレクションの偶数番目
    Debug.Print "論理ドライブのローカル名" & vbTab & Drives.Item(i)
    ' コレクションの奇数番目
    Debug.Print "UNC 共有名" & vbTab & Drives.Item(i + 1)
Next

■ 出力結果(例)
論理ドライブのローカル名 Z:
UNC 共有名 \\fileserver\共有フォルダ

■ 参考資料

EnumNetworkDrives メソッド
http://msdn.microsoft.com/ja-jp/library/cc364403.aspx

2014年10月22日水曜日

Excel から MSAccess へコピペすると、1レコード欠落する

Microsoft Excel から Access のテーブルへレコードをコピー&ペーストすると、1レコード欠落することがある。これは、Excel の「見出しチェックの機能」が影響しており、誤って見出しと識別された1行目のレコードが貼り付けられないことに起因している様子です。

Microsoftから「見出しチェックの機能」の詳しい仕様が、マイクロソフト コミュニティで提供されていました。

Access2010にてExcelからAccessテーブルへのコピー+ペーストで登録されないレコードがある
http://answers.microsoft.com/ja-jp/office/forum/office_2010-access/access2010%E3%81%AB%E3%81%A6excel%E3%81%8B/6192e312-a292-49e3-9ce5-65e15e5238d0

[VBA] RegExp.Replace で改行コードが変わってしまう

RegExp.Replace メソッドで置換したら、改行コードが CrLf から Lf になってしまう問題があります。これは行末 "$" までの置換を行った場合に起こる。

例えば、SQLのコメントを全て削るような置換パターンで発生する。
RegExp.Pattern = "--.+$"
RegExp.Replace(SQL, "")


このとき、実際は改行コード Cr まで含めた置換になっており、問題が発生します。
(置換前)ColName -- コメントCrLf    ※赤字が置換される部分
(置換後)ColName Lf
改行コード CrLf のうち、Cr が置換され消えてしまい Lf だけが残るので、改行コード CrLfLf に変換されたように感じられます。

.+(ドット プラス)や .*(ドット アアスタリスク)などの任意の文字の繰り返しパターンが問題になる。ドットは「改行文字を含まない任意の 1 文字」を表すので、リファレンスによれば、どうやら仕様通りとも言えるのだが・・・
  • $ : 入力文字列の末尾と一致します。RegExp オブジェクトの Multiline プロパティが設定されている場合、$'\n' または '\r' の直前にも一致します。
    → つまり、'\n' の直前の '\r' は一致してしまうのね。
  • .(ドット) : 改行文字 "\n" を除く任意の 1 文字に一致します。
    → つまり、キャリッジ リターン "\r" は除いていないのね。

いやいや!この仕様は無理がある。

ドットでない特定のパターンの繰り返しならば、改行コードが削られることは無い。
例えば、行末のスペースとタブのゴミを削るパターン
RegExp.Pattern = "( |\t)+$"
RegExp.Replace(SQL, "")


検証用のサンプルロジック

Const Sample As String = _
    "abc -- コメント" & vbCrLf & _
    "def" & vbCrLf & _
    "ghi"

Dim Reg As New RegExp
Reg.Global = True
Reg.MultiLine = True
Reg.Pattern = "--.+$"

Dim Text As String
Text = Reg.Replace(Sample, "")
For i = 1 To Len(Text)
    Debug.Print Mid(Text, i, 1) & vbTab & Asc(Mid(Text, i, 1))
Next

■ 参考資料

正規表現の構文
http://msdn.microsoft.com/ja-jp/library/cc392020.aspx

2014年10月18日土曜日

[VBA] 正規表現で行コメントを削除する

VBAを使って、行コメントや空行、およびタブやスペースだけの実質的な空行も削除するサンプルです。参照設定として「Microsoft VBScript Regular Expressions 5.5」が必要です。

簡略にはまとめて置換する Replace 関数で済ませたいが、改行コード CrLfLf に変わってしまった。
Dim Reg As New RegExp
Reg.MultiLine = True
Reg.Global = True

'SQL 行コメントの場合の正規表現パターン
Reg.Pattern = "--.*$"
'タブやスペースの場合の正規表現パターン
Reg.Pattern = "( |\t)+$"

Result = Reg.Replace(Text, "")


代替案として、改行コードを変更(元に戻す)するステップを加えます。

' 改行コード CrLf と Lf が混在している状態から、Lf に統一する
Text = Replace(Expression:=Text, Find:=vbCr, Replace:="", Count:=-1, Compare:=VbCompareMethod.vbBinaryCompare)
' 改行コードを Lf から CrLf に変換する
Text = Replace(Expression:=Text, Find:=vbLf, Replace:=vbCrLf, Count:=-1, Compare:=VbCompareMethod.vbBinaryCompare)


どうやら、RegExp による改行についての置換は問題がありそう。

[VBA] RegExp.Replace で改行コードが変わってしまう
http://mofuken.blogspot.jp/2014/10/vba-regexpreplace.html

■ 参考資料

Microsoft Visual Basic 6.0 で正規表現を使用する方法
http://support.microsoft.com/kb/818802

[VBA] モジュール等の名称を取得する

VBAで クラスモジュール/フォームの名称を参照する方法です。

■ クラス モジュール

Debug.Print TypeName(Me)

■ ユーザー フォーム

Debug.Print TypeName(Me)
もしくは
Debug.Print Me.Name

■ ワークシート(Excel)

Debug.Print Me.Name

標準モジュールでは Me が使えないので難しいです。

2014年10月6日月曜日

[VBA] カレントディレクトリのパスを確認する方法

VBA で開いたファイルのディレクトリを確認する方法です。

■ Word の場合

Document オブジェクトの Path プロパティを使います。
Debug.Print Me.Path

■ Excel の場合

Workbook オブジェクトの Path プロパティを使います。
Debug.Print ActiveWorkbook.Path

■ Access の場合

Database オブジェクトの Name プロパティを使います。ただしこれはファイル名まで含んでいるので、フォルダ名が欲しい場合はファイル名を削る必要があります。
(参照設定)Microsoft Scripting Runtime
Dim Fso As New FileSystemObject
Debug.Print Fso.GetParentFolderName(Database.Name)