フォルダ監視バッチ
VBAでStringを高速に扱う
VBA Recordsetの利用について
Private Sub Sample()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
'▽Recordse定義
Dim myRS As ADODB.Recordset
Set myRS = New ADODB.Recordset
With myRS.Fields
.Append "商品番号", adVarWChar, -1
.Append "番号", adVarWChar, -1
End With
myRS.Open
Dim FieldList As Variant: FieldList = Array("商品番号", "番号")
i = 2
Do
myRS.AddNew FieldList, CreateArrayData(Sheet2.Range("A" & i & ":B" & i).Resize(1, 2).Value)
i = i + 1
Loop Until IsEmpty(Sheet2.Cells(i, 1))
myRS.MoveFirst
'Recordsetデータ検索-----------------------------------------
i = 2
Do
myRS.Filter = "商品番号 = '" & Sheet1.Cells(i, 1).Value & "'"
Sheet1.Cells(i, 2) = myRS!番号
i = i + 1
If i Mod 1000 = 0 Then
End If
Loop Until IsEmpty(Sheet1.Cells(i, 1))
'閉じる
Set myRS = Nothing
Application.Calculation = xlCalculationAutomatic
End Sub
備忘録 Having句で集計関数を利用する
意外と思いつかなかったけど、HAVING句でCASE句を利用することができる
※例は適当です。グループの中で条件を満たしていないものがあるかどうかのチェックができます。
・会社ごとに振込先口座を持っている
・グループ会社の中で異なる振込先があるグループがあるか
(例)
会社CD | 会社名 | グループ会社CD | 請求会社CD | 親会社CD | 銀行CD | 支店CD | 口座番号 | 口座名義人
00001 |テスト1 | 001 | 00001 | 00001 | 0001 | 002 | 1234567 | カ)テスト1
00002 |テスト1-1 | 001 | 00002 | 00001 | 0001 | 002 | 0004567 | カ)テスト2
00003 |テスト1-2 | 001 | 00001 | 00001 | 0001 | 002 | 1234567 | カ)テスト1
10001 |テスト2 | 002 | 10001 | 10001 | 0001 | 002 | 1234567 | カ)テスト2
10002 |テスト2-1 | 002 | 10001 | 10001 | 0001 | 002 | 1234567 | カ)テスト2
-- 「請求先」が「親会社」になっていないデータが混じっているグループ会社を抽出
-- グループCDで集約を行い、グループCDでまとめた件数=レコードの中で「請求会社CD」
SELECT グループ会社CD
FROM 契約会社テーブル
GROUP BY グループ会社CD
HAVING COUNT(*) <> SUM(CASE
WHEN 請求会社CD = 親会社CD THEN 1
ELSE 0
END) AS 抽出対象
上記のデータ例で行くと「グループ会社CD:001」が抽出される
集計関数の中にもCASE式が書けるって初めて知ったときに結構衝撃だったけど、月ごとの集計結果を列で持ちたいときとかにも使えるので素晴らしい。
SELECT
商品品種名
,SUM(CASE WHEN SUBSTR(売上日,5,2) = '01' THEN 売上金額 ELSE 0 END) AS 1月売上
,SUM(CASE WHEN SUBSTR(売上日,5,2) = '02' THEN 売上金額 ELSE 0 END) AS 2月売上
,SUM(CASE WHEN SUBSTR(売上日,5,2) = '03' THEN 売上金額 ELSE 0 END) AS 3月売上
,SUM(CASE WHEN SUBSTR(売上日,5,2) = '04' THEN 売上金額 ELSE 0 END) AS 4月売上
・
・
・
FROM 売上テーブル
WHERE 売上日 BETWEEN '20210101' AND '20211231'
GROUP BY 商品品種名
Excel VBAで郵便番号・住所からカスタマーバーコードを作成
https://shiganaisenotes.blogspot.com/2011/11/blog-post.html
Public Const FIND_TEXT As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
'参照設定を追加する
'手順:[ツール] -> [参照設定] -> Microsoft VBScript Regular Expressions 5.5をチェック
Public Function CreateCustomerBarCode(strZip As String, ByVal strAddress As String) As String
Dim strRetZip As String
Dim strRetAddress As String
Dim strChar As String
Dim blnConvFlg As Boolean 'ハイフンに置き換え済みフラグ
Dim intLoop As Integer
Dim i As Integer
Dim j As Integer
Dim intCount As Integer
Dim intPos As Integer
Dim intTextLength As Integer
Dim intTargetPos As Integer
Dim strFindKeyword As String
Dim strTargetText As String
Dim strConvertText As String
Dim strTemp() As String
Dim strResult As String
Dim varConvertNum As Variant
Dim varDeleteText As Variant
Dim intFindPos As Integer
Dim objRegExp As RegExp '参照設定要(Microsoft VBScript Regular Expressions 5.5)
Dim objMatchCollect As MatchCollection
Dim objMatch As Match
Dim strTarget() As String
Dim intMatchPos() As Integer
varConvertNum = Array("1", "2", "3", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "100", "1000")
varDeleteText = Array("&", "&", "/", "/", "・", "・", ".", ".")
'郵便番号にハイフンがあったら除外します
strRetZip = Replace(strZip, "-", "", , , vbTextCompare)
'住所の全角文字を半角に変換します
strAddress = StrConv(strAddress, vbNarrow)
'住所に含まれる記号を除外します
For intLoop = 1 To UBound(varDeleteText)
strAddress = Replace(strAddress, varDeleteText(intLoop), "", , , vbTextCompare)
Next intLoop
'2つ以上連続したアルファベットを「-」へ置換する
Set objRegExp = New RegExp
'正規表現で2つ以上連続したアルファベットを検索し、「-」へ置換する。
objRegExp.Pattern = "[a-zA-Z][a-zA-Z]+"
objRegExp.Global = True '複数該当する場合に対応
strAddress = objRegExp.Replace(strAddress, "-")
'抜き出しの補足ルール
'http://www.post.japanpost.jp/zipcode/zipmanual/p19.html
'1. 漢数字が下記の特定文字の前にある場合は抜き出し対象とし、算用数字に変換して抜き出します。
'特定文字群(9種類) "丁目" "丁 " "番地" "番" "号" "地割" "線" "の" "ノ"
'1つずつ見ていく
For i = 1 To 9
strFindKeyword = ""
Select Case i
Case 1
strFindKeyword = "丁目"
Case 2
strFindKeyword = "丁"
Case 3
strFindKeyword = "番地"
Case 4
strFindKeyword = "番"
Case 5
strFindKeyword = "号"
Case 6
strFindKeyword = "地割"
Case 7
strFindKeyword = "線"
Case 8
strFindKeyword = "の"
Case 9
strFindKeyword = "ノ"
End Select
Dim ii As Integer
intPos = 0
ii = 0
'〇〇丁目〇番地 七番館 101号室 の場合に「七番館」が変換できないため、キーワードでループ
Do
'当該キーワードが見つかるか?
If ii = 0 Then
intPos = InStr(strAddress, strFindKeyword)
Else
'同じキーワードで二回目、三回目をする場合は探す住所を前回の検索結果以降にする
intPos = InStr(Mid$(strAddress, ii), strFindKeyword)
'見つかった場合は、探す住所から何文字目かどうかをチェックする
If intPos > 0 Then
intPos = intPos + ii - Len(strFindKeyword)
End If
End If
ii = ii + intPos + Len(strFindKeyword)
'見つかったら変換処理を行う。
If intPos > 0 Then
'見つかったところから左へ1つずつ移動し漢数字じゃなくなったら終了
For intCount = intPos To 2 Step -1
strTargetText = Mid$(strAddress, (intCount - 1), 1)
intTargetPos = InStr(FIND_NUM, strTargetText)
'漢数字なら継続
If intTargetPos > 0 Then
Else
'漢数字以外ならループを抜ける
Exit For
End If
Next intCount
strResult = ""
'カウントが開始位置と同一なら漢数字なしと判定して何もしない。
If intPos = intCount Then
Else
strConvertText = Mid$(strAddress, intCount, (intPos - intCount))
intTextLength = Len(strConvertText)
ReDim strTemp(intTextLength)
For j = 1 To intTextLength
intTargetPos = InStr(FIND_NUM, Mid$(strConvertText, j, 1))
strTemp(j) = varConvertNum(intTargetPos - 1)
Next j
strResult = "0"
'計算して数値を求める
For j = 1 To intTextLength
If (j = 1) Then
strResult = strTemp(j)
Else
'2桁以上なら前の桁と掛け算して足す
If Len(strTemp(j)) >= 2 Then
'すでに代入されている値が2桁以上なら足す
If Len(strResult) >= 2 Then
strResult = CStr(CInt(strResult) + (CInt(strTemp(j - 1)) * CInt(strTemp(j))))
Else
'代入されている数字が1桁なら、そのまま代入
strResult = CStr(CInt(strTemp(j - 1)) * CInt(strTemp(j)))
End If
Else
'1つ前が2桁以上か?
If Len(strTemp(j - 1)) >= 2 Then
'最終桁だったら足す
If j = intTextLength Then
strResult = CStr(CInt(strResult) + CInt(strTemp(j)))
Else
'それ以外だったら何もしないで次にまわす
End If
Else
'1桁なら結合する
strResult = strResult & strTemp(j)
End If
End If
End If
Next j
End If
'変換した結果があれば処理する
If Len(strResult) = 0 Then
Else
strAddress = Left$(strAddress, (intCount - 1)) & strResult & Mid$(strAddress, intPos)
End If
End If
Loop While intPos > 0
Next i
'住所から数字部分だけを取り出して"("で区切ります
strRetAddress = ""
blnConvFlg = True '先頭の数字以外の文字は無視する設定
For intLoop = 1 To Len(strAddress)
'1文字取り出し
strChar = Mid$(strAddress, intLoop, 1)
If IsNumeric(strChar) Then
'数字のとき
strRetAddress = strRetAddress & strChar
blnConvFlg = False
Else
'ハイフンに置き換え済みでないとき
If Not blnConvFlg Then
'アルファベットだったらそのままくっつける
intFindPos = InStr(FIND_TEXT, strChar)
If intFindPos > 0 Then
If intFindPos = 6 Then 'Fだったら特別扱い->"-"に置き換え
strRetAddress = strRetAddress & "-"
Else
If Right$(strRetAddress, 1) = "-" Then
strRetAddress = strRetAddress & strChar
Else
strRetAddress = strRetAddress & "-" & strChar & "-"
End If
End If
Else
strRetAddress = strRetAddress & "-"
End If
blnConvFlg = True
Else
'アルファベットだったらそのままくっつける
intFindPos = InStr(FIND_TEXT, strChar)
If intFindPos > 0 Then
If Right$(strRetAddress, 1) = "-" Then
strRetAddress = strRetAddress & strChar
Else
strRetAddress = strRetAddress & "-" & strChar & "-"
End If
Else
strRetAddress = strRetAddress & "-"
End If
blnConvFlg = True
End If
End If
Next intLoop
'最終処理
'連続したハイフンは1つする
objRegExp.Pattern = "\-\-+"
objRegExp.Global = True '複数該当する場合に対応
strRetAddress = objRegExp.Replace(strRetAddress, "-")
'最後と先頭のハイフンを除去します
If Left$(strRetAddress, 1) = "-" Then
strRetAddress = Mid$(strRetAddress, 2)
End If
If Right$(strRetAddress, 1) = "-" Then
strRetAddress = Left$(strRetAddress, Len(strRetAddress) - 1)
End If
'(アルファベットの前後の-(ハイフン)は取り除きます)
objRegExp.Pattern = "-*[a-zA-Z]-*"
objRegExp.Global = True '複数該当する場合に対応
'パターンマッチするものをCollectionへ格納
Set objMatchCollect = objRegExp.Execute(strRetAddress)
'1つ以上あれば以降の処理を継続
If objMatchCollect.Count > 0 Then
'配列を再定義
ReDim strTarget(objMatchCollect.Count)
ReDim intMatchPos(objMatchCollect.Count)
'複数該当に対応する
For i = 0 To (objMatchCollect.Count - 1)
'Collectionの情報を展開
Set objMatch = objMatchCollect.Item(i)
'-(ハイフン)をスペースへ変換して格納
strTarget(i + 1) = Replace(objMatch.Value, "-", " ", , , vbTextCompare)
'文字列が見つかった場所を格納
intMatchPos(i + 1) = objMatch.FirstIndex
Next i
'実際に置き換える
For i = 1 To objMatchCollect.Count
strRetAddress = Left$(strRetAddress, intMatchPos(i)) & strTarget(i) & Mid$(strRetAddress, (intMatchPos(i) + Len(strTarget(i)) + 1))
Next i
'文字列中の空白を削って終了
strRetAddress = Replace(strRetAddress, " ", "", , , vbTextCompare)
End If
'変換された郵便番号と住所を結合して返します
CreateCustomerBarCode = strRetZip & strRetAddress
End Function
Accessがインストールされていない環境でExcelからAccessファイルを作る
Accessは使いこなせば非常に有効だけど、結構高い。
使いこなせばすぐに費用対効果は出せるけど、一般の人には理解してもらえないところがある。
ただExcelはほぼ必ずと言っていいほど入っているので、Excelが入っていない環境でAccessファイルを作ることができることがわかった。
<必要な参照設定>
<コード>
’Accessファイル(.accdb)を作成
Public Sub CreateAccdbFile()
Dim objMdb As DAO.Database
Set objMdb = DBEngine.CreateDatabase("C:\Users\SampleUser\Desktop\sample.accdb", dbLangJapanese)
End Sub
バーコード読み取りソフト
Excelでバーコードを読み取りたいと思ったけど、dllをsystem32へコピーする必要があったりとちょっと今の環境ではできないことだったので、専用のexeを作ってVectorで公開した。
https://www.vector.co.jp/soft/winnt/writing/se523178.html
使い方はとっても簡単。Zxing.exeの引数にファイルパスを指定するだけ。
例)
・コマンドプロンプトを起動
・Zxing.exeのあるフォルダへ移動
・Zxing.exe c:\users\ユーザー名\DeskTop\バーコード画像.jpg
・Result.txtに結果が出力される
トリミングをする必要があるので、Excelのトリミング機能を使って、トリミングした後の画像を一時的にtemp.bmpとかに保存しておいてその画像をZxing.exeに渡してあげる。
PowerShellでWPFアプリケーションをBindingするときの注意点
1.PowerShellでWPFアプリケーションのBindingについて マニアックだけどPowerShellでWPFアプリケーションを作っている。INotifyChangedを実装したいけど、PowerShellにはgetterやsetterがないので通知が発行できない。 そ...
-
TreeListView上でコンボボックスを利用するときにフォーカスのあるコンボボックスの色をイベントで変えようとしたけど上手くいかなかった。 色々と調べているとXaml側のテンプレートをいじる必要があるみたいだったので、いろいろとやってみた。 とりあえず、コンボボックス...
-
PDFファイルが大量にあるため、中身を検索する方法がないか調べたときのメモ ・外部のdllは必須っぽい ・PowerShell単独や.NET Frameworkなどの利用だけではどうにもならない ちょっと調べるだけでもiTextSharpが使えそうだったので利用する。 1....
-
Excelマクロでカスタマーバーコードのもとになるデータを作る必要があったので、調べてみたらいい古い記事だけどわかりやすいプログラムを記載しているブログがあった。 https://shiganaisenotes.blogspot.com/2011/11/blog-post.ht...