なぜVBAなのか?
- 開発環境構築が楽(Excelが入っていればOK)
- 導入できるソフトウェアに制限がある
ソースコード
mylib.bas
Option Explicit
'-------------------------------------------------------------------------------
' 指定時間プログラムを停止する。
'-------------------------------------------------------------------------------
' note : ミリ秒で指定。WindowsAPI。
'-------------------------------------------------------------------------------
Public Declare Sub Sleep Lib "kernel32" (ByVal ms As Long)
'-------------------------------------------------------------------------------
' 列名から列位置を取得する。
'-------------------------------------------------------------------------------
' param : aTargetSheet
' param : aColumnName 列名
' param : aRowIndexOfClomunName 列名が存在する行の位置
' return : 列名が存在する列の位置
'-------------------------------------------------------------------------------
Public Function GetColIndex(pTargetSheet As Worksheet, aColumnName As String, Optional pRowIndexOfClomunName As Long = 0) As String
GetColIndex = WorksheetFunction.Match(pColumnName, pTargetSheet.rows(pRowIndexOfClomunName), 0) '0:完全一致
End Function
'-------------------------------------------------------------------------------
' 文字列配列を検索し位置を返す。
'-------------------------------------------------------------------------------
' param : pArray 文字列配列
' param : searchString 検索文字列
' return : 文字列配列の位置。検索にヒットしない場合は-1を返す。
'-------------------------------------------------------------------------------
Public Function IndexOf(pArray As Variant, searchString As String) As Long
Dim i As Long
For i = 0 To UBound(pArray)
If pArray(i) = searchString Then
IndexOf = i
Exit Function
End If
Next
IndexOf = -1
End Function
'-------------------------------------------------------------------------------
' コマンド(~.exe)を実行する。
' またはファイルに関連付けられたアプリケーションを起動する
'-------------------------------------------------------------------------------
' param : pCommand コマンドまたはファイルパス
' param : pWindowStyle 0:ウィンドウ非表示
' 1:通常ウィンドウ
' param : pIsSync false:非同期
' true :同期
' return : 実行結果
' note : vbs対応のため、型定義なし
'-------------------------------------------------------------------------------
Public Function ExecCommand( _
pCommand, _
pWindowStyle, _
pIsSync As Boolean)
Dim wss
Set wss = CreateObject("WScript.Shell")
ExecCommand = wss.Run(pCommand, pWindowStyle, pIsSync)
End Function
'-------------------------------------------------------------------------------
' 多階層フォルダ作成(複数階層フォルダ作成)
'-------------------------------------------------------------------------------
' param : pFolderPath フォルダパス
' return :
' note : d:\tempというフォルダ構成に対して
' d:\temp\first\secondというフォルダを作成できる
' 一般的なフォルダ作成はfirstフォルダが存在していない場合エラー
' vbs対応のため、型定義なし
' dependence : ExecCommand
'-------------------------------------------------------------------------------
Public Sub MakeFolder(pFolderPath)
Call ExecCommand("cmd /c MD " & pFolderPath, 0, True)
End Sub
'-------------------------------------------------------------------------------
' フォルダパス文字列を結合する
'-------------------------------------------------------------------------------
' param : aFolderPath フォルダパス
' return :
' note : JF("d:\tmp", "backup") ⇒ d:\tmp\backup
'-------------------------------------------------------------------------------
Public Function JF(ParamArray pFolderPathArray() As Variant) As String
Dim path As String
Dim folderPath As Variant
For Each folderPath In pFolderPathArray
path = path & FormatFolderPath(CStr(folderPath))
Next
JF = path
End Function
'-------------------------------------------------------------------------------
' フォルダパス文字列の書式修正
'-------------------------------------------------------------------------------
' param : pFolderPath フォルダパス文字列
' return :
' note :
' FormatFolderPath("c:\dummy") → c:\dummy
' FormatFolderPath("c:\dummy\") → c:\dummy
' FormatFolderPath("subdir") → \subdir
' FormatFolderPath("\subdir\") → \subdir
' FormatFolderPath("\\nethoge\duumy")→ \\nethoge\dummy
' FormatFolderPath("\\nethoge\duumy\")→ \\nethoge\dummy
'-------------------------------------------------------------------------------
Private Function FormatFolderPath( _
pFolderPath As String)
Dim folderPath
folderPath = pFolderPath
'先頭に対する処理
If Mid(folderPath, 1, 2) = "\\" Or Mid(folderPath, 2, 1) = ":" Then
'処理なし
ElseIf Mid(folderPath, 1, 1) <> "\" Then
folderPath = "\" & folderPath
End If
'末尾に対する処理
If Right(folderPath, 1) = "\" Then
folderPath = Mid(folderPath, 1, Len(folderPath) - 1)
End If
FormatFolderPath = folderPath
End Function
'-------------------------------------------------------------------------------
' エクスプローラーを開く
'-------------------------------------------------------------------------------
' param : pFolderPath フォルダパス
'-------------------------------------------------------------------------------
Public Sub OpenExplorer( _
pFolderPath As String)
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
If Not fso.folderexists(pFolderPath) Then
MsgBox "フォルダを指定してください" & vbCrLf & pFolderPath
Exit Sub
End If
CreateObject("Shell.Application").ShellExecute pFolderPath
End Sub
'-------------------------------------------------------------------------------
' エクスプローラーを開く(ファイルを選択状態にする)
'-------------------------------------------------------------------------------
' param : pFilePath
' dependence : Sleep、OpenExplorer
'-------------------------------------------------------------------------------
Public Sub OpenExplorerFileSelected( _
pFilePath As String)
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Dim folderPath As String
folderPath = fso.GetParentFolderName(pFilePath)
OpenExplorer folderPath
Dim wb As Object
Do While wb Is Nothing
Sleep 500
Set wb = GetExplorer(folderPath)
Loop
Call wb.document.SelectItem(CVar(pFilePath), 21) '1+4+16
End Sub
Private Function GetExplorer( _
pFolder) As Object
Dim objExp
Set objExp = CreateObject("Shell.Application")
Dim wb As Object
For Each wb In objExp.Windows
If wb.Name = "エクスプローラー" _
And LCase(wb.document.folder.Self.path) = LCase(pFolder) Then
Set GetExplorer = wb
Exit Function
End If
Next
End Function
'-------------------------------------------------------------------------------
' ファイルまたはフォルダをコピーする。
'-------------------------------------------------------------------------------
' param : pSrcPath コピー元ファイルパス(コピー元フォルダパス)
' param : pDestPath コピー先ファイルパス(コピー先フォルダパス)
' note : フォルダの場合は末尾の「\」有無で動作が変わらないように対応
' vbs対応のため、型定義なし
' dependence: JF
'-------------------------------------------------------------------------------
Public Sub CopyItem(pSrcPath, pDestPath)
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.folderexists(pSrcPath) Then
If fso.folderexists(pDestPath) Then
fso.CopyFolder JF(pSrcPath), JF(pDestPath) & "\", True 'True:上書き
Else
fso.CopyFolder JF(pSrcPath), JF(pDestPath), True 'True:上書き
End If
ElseIf fso.FileExists(pSrcPath) Then
If fso.folderexists(pDestPath) Then
fso.CopyFile pSrcPath, JF(pDestPath) & "\", True 'True:上書き
Else
fso.CopyFile pSrcPath, pDestPath, True 'True:上書き
End If
Else
Err.Raise 1, , "CopyItemが失敗しました(独自エラー)"
End If
End Sub
'-------------------------------------------------------------------------------
' ファイルまたはフォルダを削除する。
'-------------------------------------------------------------------------------
' param : pSrcPath 削除するファイルまたフォルダのパス
' note : フォルダの場合は末尾の「\」有無で動作が変わらないように対応
' vbs対応のため、型定義なし
' dependence: JF
'-------------------------------------------------------------------------------
Public Sub DeleteItem(pSrcPath)
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.folderexists(pSrcPath) Then
fso.DeleteFolder JF(pSrcPath), False 'False:読み取り専用を削除しない
ElseIf fso.FileExists(pSrcPath) = True Then
fso.DeleteFile pSrcPath, False 'False:読み取り専用を削除しない
Else
Err.Raise 1, , "DeleteItemが失敗しました(独自エラー)"
End If
End Sub
'-------------------------------------------------------------------------------
' ファイルまたはフォルダを移動する。
'-------------------------------------------------------------------------------
Public Sub MoveItem(pSrcPath, pDestPath)
CopyItem pSrcPath, pDestPath
DeleteItem pSrcPath
End Sub
'-------------------------------------------------------------------------------
' 文字列をファイルに書き込む。
'-------------------------------------------------------------------------------
' param : pFilePath ファイルパス
' param : pText 書き込む文字列
' param : pAdditionalMode true :追加書き込み
' * false:通常書き込み
' param : pEncoding * 0 : utf-8 BOMなし
' 1 : shift_jis
' dependence: MakeFolder
' note : フォルダが存在していなければ作成する。
' : FSO版はUTF-8に対応していないため廃止。
'-------------------------------------------------------------------------------
Public Sub WriteFile( _
pFilePath As String, _
pText As String, _
Optional pAdditionalMode As Boolean = False, _
Optional pEncoding As Long = 0)
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Dim folderPath As String
folderPath = fso.GetParentFolderName(pFilePath)
If Not fso.folderexists(folderPath) Then
Call MakeFolder(folderPath)
End If
With CreateObject("ADODB.Stream")
If pEncoding = 0 Then
.Charset = "utf-8"
ElseIf pEncoding = 1 Then
.Charset = "shift_jis"
End If
.Open
'追加書き込みの場合、書き込み位置を末尾に移動。
If pAdditionalMode And fso.FileExists(pFilePath) Then
.LoadFromFile pFilePath
.Position = .Size
End If
.WriteText pText, 0 '0:末尾改行なし
'utf-8の場合、BOM削除
If pEncoding = 0 Then
.Position = 0
.Type = 1 'バイナリ―モード
.Position = 3
Dim bin As Variant
bin = .Read()
.Position = 0
If Not IsNull(bin) Then
.Write = bin
End If
.SetEos
End If
.SaveToFile pFilePath, 2 '2:同名ファイルが存在してもエラーとしない
.Close
End With
End Sub
'-------------------------------------------------------------------------------
' テキストファイルの文字列を全て取得する。
'-------------------------------------------------------------------------------
' param : pFilePath ファイルパス
' : pEncodingType 文字コードタイプ * 0 : utf-8
' 1 : shift_jis
' : pLineSeparator 改行文字 * vbCrLf
' return : Variant(String配列)
' note : FSO版はUTF-8に対応していないため廃止
'-------------------------------------------------------------------------------
Public Function ReadFile( _
pFilePath As String, _
Optional pEncodingType As Long = 0, _
Optional pLineSeparator As String = vbCrLf _
) As Variant
With CreateObject("ADODB.Stream")
If pEncodingType = 0 Then
.Charset = "utf-8"
ElseIf pEncodingType = 1 Then
.Charset = "shift_jis"
End If
.Open
.LoadFromFile pFilePath
Dim arr As Variant
arr = Split(.ReadText, pLineSeparator)
ReadFile = arr
.Close
End With
End Function
'-------------------------------------------------------------------------------
' プロパティファイルを読み込む。
'-------------------------------------------------------------------------------
' param : pFilePath ファイルパス
' return : プロパティ(Dictionary型)
' note :
' Dim properties As Object
' Set properties = ReadProperties("ファイルパス")
' Debug.Print properties.item("キー")
'-------------------------------------------------------------------------------
Public Function ReadProperties(pFilePath As String) As Object
Dim properties As Object
Set properties = CreateObject("Scripting.Dictionary")
Dim rows() As String
rows() = ReadFile(pFilePath)
Dim row As Variant
For Each row In rows
If row = "" Then
GoTo continue1
End If
Dim key As String
Dim value As String
Dim var As Variant
var = Split(row, "=")
key = var(0)
value = var(1)
If key = "" Then
GoTo continue1
End If
properties.Add key, value
continue1:
Next
Set ReadProperties = properties
End Function
'-------------------------------------------------------------------------------
' 一時ファイルパス文字列を生成する
'-------------------------------------------------------------------------------
' param : pPathTail 拡張子を付けたい場合に指定する。例 ".bat"
' return : 生成した一時ファイルパス文字列
'-------------------------------------------------------------------------------
Public Function CreateTempFilePath( _
Optional pPathTail = "") As String
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
CreateTempFilePath = fso.GetSpecialFolder(2) & _
"\" & fso.GetBaseName(fso.GetTempName) & pPathTail
End Function
'-------------------------------------------------------------------------------
' テンプレート文字列に変数展開する
'-------------------------------------------------------------------------------
' param : pTemplateText テンプレート文字列
' param : pVal() 設定値
' return : 変数展開した文字列
' note : Here("私は${0}が${1}です", "ラーメン", "好き")
'-------------------------------------------------------------------------------
Public Function Here(pTemplateText, ParamArray pVal())
Const PRE As String = "${"
Const SUF As String = "}"
Dim text As String
text = pTemplateText
Dim i As Long
For i = 0 To UBound(pVal)
text = Replace(text, PRE & i & SUF, pVal(i))
Next
Here = text
End Function
'-------------------------------------------------------------------------------
' DBコネクションを取得する
'-------------------------------------------------------------------------------
' param :
' return :
' note :
' DB接続文字列の例
' 例1 Provider=OraOLEDB.Oracle;
' Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)
' (HOST=localhost)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=XE)));
' User ID=scott;Password=tiger
' 例2 DSN=oracle xe;UID=scott;PWD=tiger
'-------------------------------------------------------------------------------
Public Function GetDBConnection(aDBConnectionString As String) As Object
Dim cn As Object
Set cn = CreateObject("ADODB.Connection")
cn.Open aDBConnectionString
Set GetDBConnection = cn
End Function
'-------------------------------------------------------------------------------
' 正規表現検索に使用するRegExpオブジェクトを作成する。
'-------------------------------------------------------------------------------
' param : pPattern 正規表現パターン
' param retrun: rObjRegExp RegExpオブジェクト
' note :
' '[How to use]
' Dim regExpAbc As Object
' CreateRegExp "c(c.+d)e", regExpAbc
' Dim ms As Object
' Dim m As Object
' Set ms = regExpAbc.Execute("aabbccddee")
' For Each m In ms
' Debug.Print m.value '⇒ ccdde
' Debug.Print m.submatches(0) '⇒ cdd
' Next
'
' 'replace
' Dim str As String
' str = regExpAbc.Replace("aabbccddee", "xxx") '⇒ aabbxxxe
'
'-------------------------------------------------------------------------------
Public Sub CreateRegExp(pPattern As String, ByRef prObjRegExp As Object)
Set prObjRegExp = CreateObject("VBScript.RegExp")
prObjRegExp.pattern = pPattern
prObjRegExp.IgnoreCase = False 'False:大文字と小文字を区別する
prObjRegExp.Global = True 'True:文字列全体を検索、False:1回目のマッチで終了
prObjRegExp.multiLine = True 'True:通常、False:^や$が文字列全体の先頭と末尾になる
End Sub
'オブジェクトのcountが1件以上の場合trueを返す
Public Function HasItems(obj As Object)
If Not obj Is Nothing And obj.Count >= 1 Then
HasItems = True
Exit Function
End If
HasItems = False
End Function
'-------------------------------------------------------------------------------
' batファイルを実行する。
'-------------------------------------------------------------------------------
' param : pBatFilePath batファイルパス
' return : batファイルの戻り値
' note :
'-------------------------------------------------------------------------------
Public Function ExecBat(pBatFilePath As String) As Long
ExecBat = ExecCommand(pBatFilePath, 1, True)
End Function
'-------------------------------------------------------------------------------
' シートが1個の新規ブックを作成する。
'-------------------------------------------------------------------------------
' param :
' return : 新規ブック
' note :
'-------------------------------------------------------------------------------
Public Function CreateOneSheetBook() As Workbook
Dim bakSheetCount As Integer
bakSheetCount = Application.SheetsInNewWorkbook
Application.SheetsInNewWorkbook = 1
Dim resultBook As Workbook
Set resultBook = Workbooks.Add
resultBook.Sheets(1).Cells.Font.Name = "MS ゴシック"
Application.SheetsInNewWorkbook = bakSheetCount
Set CreateOneSheetBook = resultBook
End Function
'-------------------------------------------------------------------------------
' ワークシートの最終行の行位置を取得する
'-------------------------------------------------------------------------------
' param : pSheet ワークシート
' param : pCol 最終行を検証する列位置
' return : 最終行の行位置
' note : UsedRangeはセルに値が無くても罫線や色が設定されていると行位置
' として検出されてしまう。
' findメソッド版は検索と置換ダイアログに影響がある為、廃止。
'-------------------------------------------------------------------------------
Public Function GetLastRow( _
pSheet As Worksheet, _
Optional pCol As Long = 0) As Long
Dim row As Long
If pCol = 0 Then
row = pSheet.UsedRange.rows(pSheet.UsedRange.rows.Count).row
Else
row = pSheet.Cells(pSheet.rows.Count, pCol).End(xlUp).row
End If
GetLastRow = row
End Function
'-------------------------------------------------------------------------------
' ワークシートの最終列の列位置を取得する
'-------------------------------------------------------------------------------
' param : pSheet ワークシート
' param : pRow 最終列を検証する行位置
' return : 最終列の列位置
' note : sedRangeはセルに値が無くても罫線や色が設定されていると行位置
' として検出されてしまう。
' findメソッド版は検索と置換ダイアログに影響がある為、廃止。
'-------------------------------------------------------------------------------
Public Function GetLastColumn( _
pSheet As Worksheet, _
Optional pRow As Long = 0) As Long
Dim col As Long
If pRow = 0 Then
col = pSheet.UsedRange.Columns(pSheet.UsedRange.Columns.Count).Column
Else
col = pSheet.Cells(pRow, pSheet.Columns.Count).End(xlToLeft).Column
End If
GetLastColumn = col
End Function
'-------------------------------------------------------------------------------
' CSVファイルをExcelで開く QueryTables版
'-------------------------------------------------------------------------------
' param : pCsvFilePath CSVファイルパス
' param : pSeparator 区切り文字
' param : aEncoding * 65001:UTF-8
' 932:Shift-JIS
' param : pHeadingWindowLockFlag ヘッダ部ウィンドウ固定
'-------------------------------------------------------------------------------
Public Sub OpenCsv( _
pCsvFilePath As String, _
Optional pSeparator As String = ",", _
Optional pEncoding As Long = 65001, _
Optional pHeadingWindowLockFlag As String = False)
Dim columnDataTypes(255) As Long
Dim i As Long
For i = 0 To 255
columnDataTypes(i) = 2 '2:xlTextFormat
Next
Dim newSheet As Worksheet
Set newSheet = CreateOneSheetBook.Sheets(1)
newSheet.Cells.Font.Name = "MS ゴシック"
Dim qt As QueryTable
Set qt = newSheet.QueryTables.Add(Connection:="text;" & pCsvFilePath, _
Destination:=newSheet.Range("A1"))
qt.TextFileOtherDelimiter = pSeparator
qt.TextFileColumnDataTypes = columnDataTypes
qt.TextFilePlatform = pEncoding
qt.Refresh
qt.Delete
newSheet.Cells.Columns.AutoFit
If pHeadingWindowLockFlag Then
newSheet.Range("A2").Select
ActiveWindow.FreezePanes = False
ActiveWindow.FreezePanes = True
End If
End Sub
'-------------------------------------------------------------------------------
' ブックが開いているかチェック
'-------------------------------------------------------------------------------
Public Function IsOpenedBook( _
pBookName As String) As Boolean
IsOpenedBook = False
Dim book As Workbook
For Each book In Workbooks
If book.Name = pBookName Then
IsOpenedBook = True
Exit Function
End If
Next
End Function
'-------------------------------------------------------------------------------
' シート存在チェック
'-------------------------------------------------------------------------------
Public Function ExistsSheet( _
pBook As Workbook, _
pSheetName As String) As Boolean
Dim sheet As Worksheet
For Each sheet In pBook.Worksheets
If sheet.Name = pSheetName Then
ExistsSheet = True
Exit Function
End If
Next
ExistsSheet = False
End Function
'-------------------------------------------------------------------------------
' 配列の最後に値を追加
'-------------------------------------------------------------------------------
' param : pArray 配列
' return : pValue 値
' note : pArrayに要素数未指定の配列変数を指定するとエラーになる。
' その場合はArray()で初期化して渡す。
' Dim arr As Variant
' arr = Array()
' Call AddArray(arr,"hoge")
'-------------------------------------------------------------------------------
Public Function AddArray( _
ByRef pArray As Variant, _
pValue As Variant)
ReDim Preserve pArray(UBound(pArray) + 1)
pArray(UBound(pArray)) = pValue
End Function
'-------------------------------------------------------------------------------
' ブック、シートの体裁を整える
'-------------------------------------------------------------------------------
Public Sub FormatBook()
'各シートの体裁を整える
Dim sheet As Worksheet
For Each sheet In ActiveWorkbook.Sheets
If sheet.Visible = True Then
sheet.Activate
'表示倍率 85%
ActiveWindow.Zoom = 85
'A1セルを選択
Application.Goto sheet.Range("A1"), True
End If
Next
'先頭シートを選択
Dim i As Long
For i = 1 To ActiveWorkbook.Sheets.Count
If ActiveWorkbook.Sheets(i).Visible = True Then
ActiveWorkbook.Sheets(i).Select
Exit Sub
End If
Next
End Sub