LoginSignup
1
2

More than 3 years have passed since last update.

GOLD29VBA

Last updated at Posted at 2019-01-20

Excel

image.png

=IFERROR(VLOOKUP($F4,INDEX($B$2:$B$8,MATCH($F4,$B$2:$B$8,0)+I$1-1):$C$8,2,FALSE),"")

image.png

=VLOOKUP("*",IF(COUNTIF(C$1:C1,$B$1:$B$9)=0,$B$1:$B$9),1,FALSE)

SQL

Option Explicit


'==========================================================
'データ取得サンプル
'==========================================================
Public Sub GetDataSample()

  Dim temporaryBook As Workbook
  Dim connection    As Object
  Dim recordset     As Object
  Dim sql           As String
  Dim row           As Long

  'ADODBコネクション用Bookを用意
  Set temporaryBook = makeTemporaryBook ': If temporaryBook Is Nothing Then GoTo ERR_END
  GetSheetToBook ThisWorkbook.Worksheets("SQL1").Range("A1"), temporaryBook, "SQL1"
  GetSheetToBook ThisWorkbook.Worksheets("SQL2").Range("A1"), temporaryBook, "SQL2"

  'コネクションを確立
  Set connection = GetADODBConnection(temporaryBook)

  '抽出条件を作成
  sql = "SELECT" _
      & "  B.日本語 " _
      & " FROM [SQL1$] AS A" _
      & "  LEFT OUTER JOIN [SQL2$] AS B" _
      & "   ON A.ID=B.ID AND A.ひらがな=B.ひらがな;" _

  '抽出実行
  If Not getADODBRecordset(connection, sql, recordset) Then GoTo ERR_END

  '抽出結果を出力

'  'フィールド(項目)名を出力
'    For row = 0 To recordset.Fields.Count - 1
'      .Offset(, row).Value = recordset.Fields(row).Name
'    Next row

  '①データを出力
  ThisWorkbook.Worksheets("SQL1").Cells(2, 3).CopyFromRecordset recordset

  '②データを出力
'  row = 2
'  Do Until recordset.EOF
'      ThisWorkbook.Worksheets("SQL1").Cells(row, 3).Value = recordset!日本語
'      recordset.MoveNext
'      row = row + 1
'  Loop


  GoTo FIN

ERR_END:

  MsgBox "エラーですよ"


FIN:

  'レコードセットを閉じる
  CloseRecordSet recordset

  'コネクションを閉じる
  CloseConnection connection

  DeleteBook temporaryBook

End Sub


Function makeTemporaryBook() As Workbook
  Const TEMPORARY_BOOK_NAME = "TEMPORARY_BOOK_FOR_SQL.xlsx"

  Dim newBook As Workbook

  On Error Resume Next
  Set newBook = Application.Workbooks(TEMPORARY_BOOK_NAME)
  On Error GoTo 0

  If Not newBook Is Nothing Then
    DeleteBook newBook
  End If

  Set newBook = Workbooks.Add

  Application.DisplayAlerts = False
  newBook.SaveAs ThisWorkbook.Path & "\" & "TEMPORARY_BOOK_FOR_SQL", xlWorkbookDefault
  Application.DisplayAlerts = True

  Set makeTemporaryBook = newBook

End Function

Function DeleteBook(book As Workbook) As Boolean

  Dim fullname As String
  fullname = book.fullname

  On Error GoTo ERR_END

  book.Close
  Set book = Nothing
  Kill fullname

  On Error GoTo 0

  DeleteBook = True

  GoTo FIN

ERR_END:
  Debug.Print "DeleteBook:削除失敗"
FIN:
End Function


'==========================================================
'GetSheetToBook
'----------------------------------------------------------
'エクセルの表を特定Bookの白紙SheetのA1セルにコピーする
'その際、白紙Sheetに名前を付ける
'==========================================================
Public Sub GetSheetToBook( _
      table_top_left_range_of_src_sheet As Range _
    , destination_book As Workbook _
    , new_sheet_name_as_table_name As String _
)
  Const A1_CELL As String = "A1"
  Dim srcSheet As Worksheet
  Dim tableBottomRightRange As Range
  Dim tableRange As Range
  Dim dstSheet As Worksheet

  With table_top_left_range_of_src_sheet.CurrentRegion
    Set tableBottomRightRange = .Cells(.Rows.Count, .Columns.Count)
  End With

  Set srcSheet = table_top_left_range_of_src_sheet.Parent
  Set tableRange = srcSheet.Range(table_top_left_range_of_src_sheet, tableBottomRightRange)

  With destination_book.Worksheets(1).Range(A1_CELL).SpecialCells(xlCellTypeLastCell)
    If .Address(False, False) = A1_CELL And .Value = Empty Then
      Set dstSheet = destination_book.Worksheets(1)
    Else
      With destination_book
        Set dstSheet = .Worksheets.Add(After:=.Worksheets(.Worksheets.Count))
      End With
    End If
  End With

  dstSheet.Name = new_sheet_name_as_table_name
  tableRange.Copy
  With dstSheet.Range(A1_CELL)
    .PasteSpecial xlPasteFormats
    .PasteSpecial xlPasteValues
  End With

  Application.DisplayAlerts = False
  destination_book.Save
  Application.DisplayAlerts = True

End Sub




'==========================================================
'GetADODBConnection
'==========================================================
Public Function GetADODBConnection(data_source_book As Workbook) As Object

  Dim ADODBConnection As Object
  Dim connectionString As String

  Set ADODBConnection = CreateObject("ADODB.Connection")

  connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" _
                   & "Data Source=" & data_source_book.fullname & ";" _
                   & "Extended Properties=""Excel 8.0;" _
                   & "HDR=Yes"";"
  ADODBConnection.Open connectionString

  Set GetADODBConnection = ADODBConnection

End Function

'==========================================================
'GetRecordset
'==========================================================
Public Function getADODBRecordset( _
                        ByRef connection As Object, _
                        ByVal SQL_string As String, _
                        ByRef record_set As Object _
                        ) As Boolean
  Const adOpenDynamic       As Long = 2
  Const adLockOptimistic    As Long = 3

  On Error GoTo ERR_END

  Set record_set = CreateObject("ADODB.Recordset")

  record_set.Open SQL_string, connection, adOpenDynamic, adLockOptimistic

  getADODBRecordset = True

  GoTo FIN

ERR_END:

  MsgBox "getRecordsetにてエラー"

FIN:

End Function


'==========================================================
'コネクション破棄
'==========================================================
Public Sub CloseConnection(objCN As Object)

  Const adStateClosed = 0

  If objCN Is Nothing Then Exit Sub

  If objCN.State <> adStateClosed Then

    objCN.Close

  End If

  Set objCN = Nothing

End Sub

'==========================================================
'レコードセット破棄
'==========================================================
Public Sub CloseRecordSet(objRS As Object)

  Const adStateClosed = 0

  If objRS Is Nothing Then Exit Sub

  If objRS.State <> adStateClosed Then

    objRS.Close

  End If

  Set objRS = Nothing

End Sub

ダウンロード

'======
Sub testGetIEObject()
Dim ie As Object
Set ie = GetIEObject("https://photos.google.com/u/1/photo/AF1QipNlu2ACuq8nktSQuBWFIEjzl9oh2DU-BYCIEKJy")
ファイルダウンロードSample ie
End Sub

'=====================================================----

'以下の情報を元に作成
'https://www.ka-net.org/blog/?p=4855

Public Sub ファイルダウンロードSample(ie As Object)
  With ie
    DownloadFileNbOrDlg .hwnd, "C:\Users\Tom\Documents\自作\Excel遊びテスト3"
  End With
End Sub


Private Sub DownloadFileNbOrDlg(ByVal hIE As Long, ByVal SaveFilePath As String)
'通知バー/Internet Explorerダイアログを操作してファイルをダウンロード
'※ UIAutomationClient(%SYSTEMROOT%\system32\UIAutomationCore.dll)要参照
'
' - hIE:InternetExplorerのハンドル
' - SaveFilePath:ファイルのダウンロード先
'
'http://okwave.jp/qa/q8121989.html
'http://okwave.jp/qa/q8320348.html
'https://gist.github.com/kumatti1/7957796 参考

  Dim uiAuto As CUIAutomation
  Dim elmIE As IUIAutomationElement
  Dim elmNotificationBar As IUIAutomationElement
  Dim elmSaveSplitButton As IUIAutomationElement
  Dim elmSaveDropDownButton As IUIAutomationElement
  Dim elmSaveMenu As IUIAutomationElement
  Dim elmSaveMenuItem As IUIAutomationElement
  Dim elmIEDialog As IUIAutomationElement
  Dim elmSaveAsButton As IUIAutomationElement
  Dim elmSaveAsWindow As IUIAutomationElement
  Dim elmFileNameEdit As IUIAutomationElement
  Dim elmSaveButton As IUIAutomationElement
  Dim elmNotificationText As IUIAutomationElement
  Dim elmCloseButton As IUIAutomationElement
  Dim iptn As IUIAutomationInvokePattern
  Dim vptn As IUIAutomationValuePattern
  Const ROLE_SYSTEM_BUTTONDROPDOWN = &H38&

  Set uiAuto = New CUIAutomation
  Set elmIE = uiAuto.ElementFromHandle(ByVal hIE)

  'ファイルを事前に削除
  With CreateObject("Scripting.FileSystemObject")
    If .FileExists(SaveFilePath) Then .DeleteFile SaveFilePath, True
  End With

  Do
    '[通知バー]取得
    Set elmNotificationBar = _
      GetElement(uiAuto, _
                 elmIE, _
                 UIA_AutomationIdPropertyId, _
                 "IENotificationBar", _
                 UIA_ToolBarControlTypeId)

    '[Internet Explorer]ダイアログ((ファイル名) で行う操作を選んでください)取得
    Set elmIEDialog = _
      GetElement(uiAuto, _
                 elmIE, _
                 UIA_NamePropertyId, _
                 "Internet Explorer", _
                 UIA_WindowControlTypeId)
    DoEvents
  Loop Until (Not elmNotificationBar Is Nothing) Or _
             (Not elmIEDialog Is Nothing)

  '***** 通知バー操作ここから *****
  If Not elmNotificationBar Is Nothing Then
    '[保存]スプリットボタン取得
    Set elmSaveSplitButton = _
      GetElement(uiAuto, _
                 elmNotificationBar, _
                 UIA_NamePropertyId, _
                 "保存", _
                 UIA_SplitButtonControlTypeId)
    If elmSaveSplitButton Is Nothing Then GoTo Fin

    '[保存]ドロップダウン取得
    Set elmSaveDropDownButton = _
      GetElement(uiAuto, _
                 elmNotificationBar, _
                 UIA_LegacyIAccessibleRolePropertyId, _
                 ROLE_SYSTEM_BUTTONDROPDOWN, _
                 UIA_SplitButtonControlTypeId)
    If elmSaveDropDownButton Is Nothing Then GoTo Fin

    '[保存]ドロップダウン押下 -> [名前を付けて保存(A)]ボタン押下
    Set iptn = elmSaveDropDownButton.GetCurrentPattern(UIA_InvokePatternId)
    Do
      iptn.Invoke
      Sleep 300
      Set elmSaveMenu = _
        GetElement(uiAuto, _
                   uiAuto.GetRootElement, _
                   UIA_ClassNamePropertyId, _
                   "#32768", _
                   UIA_MenuControlTypeId)
      DoEvents
    Loop While elmSaveMenu Is Nothing
    Set elmSaveMenuItem = _
      GetElement(uiAuto, _
                 elmSaveMenu, _
                 UIA_NamePropertyId, _
                 "名前を付けて保存(A)", _
                 UIA_MenuItemControlTypeId)
    If elmSaveMenuItem Is Nothing Then GoTo Fin
    Set iptn = elmSaveMenuItem.GetCurrentPattern(UIA_InvokePatternId)
    iptn.Invoke
  End If
  '***** 通知バー操作ここまで *****

  '***** Internet Explorerダイアログ操作ここから *****
  If Not elmIEDialog Is Nothing Then
    Set elmSaveAsButton = _
      GetElement(uiAuto, _
                 elmIEDialog, _
                 UIA_NamePropertyId, _
                 "名前を付けて保存(A)", _
                 UIA_ButtonControlTypeId)
    If elmSaveAsButton Is Nothing Then GoTo Fin
    Set iptn = elmSaveAsButton.GetCurrentPattern(UIA_InvokePatternId)
    iptn.Invoke
  End If
  '***** Internet Explorerダイアログ操作ここまで *****

  If (elmNotificationBar Is Nothing) And (elmIEDialog Is Nothing) Then GoTo Fin

  '***** 名前を付けて保存操作ここから *****
  Sleep 300
  '[名前を付けて保存]ダイアログ取得
  Do
    Set elmSaveAsWindow = _
      GetElement(uiAuto, _
                 uiAuto.GetRootElement, _
                 UIA_NamePropertyId, _
                 "名前を付けて保存", _
                 UIA_WindowControlTypeId)
    DoEvents
  Loop While elmSaveAsWindow Is Nothing

  '[ファイル名]欄取得 -> ファイルパス入力
  Set elmFileNameEdit = _
    GetElement(uiAuto, _
               elmSaveAsWindow, _
               UIA_NamePropertyId, _
               "ファイル名:", _
               UIA_EditControlTypeId)
  If elmFileNameEdit Is Nothing Then GoTo Fin
  Set vptn = elmFileNameEdit.GetCurrentPattern(UIA_ValuePatternId)
  vptn.SetValue SaveFilePath

  '[保存(S)]ボタン押下
  Set elmSaveButton = _
    GetElement(uiAuto, _
               elmSaveAsWindow, _
               UIA_NamePropertyId, _
               "保存(S)", _
               UIA_ButtonControlTypeId)
  If elmSaveButton Is Nothing Then GoTo Fin
  Set iptn = elmSaveButton.GetCurrentPattern(UIA_InvokePatternId)
  iptn.Invoke
  '***** 名前を付けて保存操作ここまで *****

  '***** ダウンロード完了待ちここから *****
  If elmNotificationBar Is Nothing Then
    '[通知バー]取得
    Do
      Set elmNotificationBar = _
        GetElement(uiAuto, _
                   elmIE, _
                   UIA_AutomationIdPropertyId, _
                   "IENotificationBar", _
                   UIA_ToolBarControlTypeId)
      DoEvents
    Loop While elmNotificationBar Is Nothing
  End If

  '[通知バーのテキスト]取得
  Set elmNotificationText = _
    GetElement(uiAuto, _
               elmNotificationBar, _
               UIA_NamePropertyId, _
               "通知バーのテキスト", _
               UIA_TextControlTypeId)
  If elmNotificationText Is Nothing Then GoTo Fin

  '[閉じる]ボタン取得
  Set elmCloseButton = _
    GetElement(uiAuto, _
               elmNotificationBar, _
               UIA_NamePropertyId, _
               "閉じる", _
               UIA_ButtonControlTypeId)
  If elmCloseButton Is Nothing Then GoTo Fin

  Do
    DoEvents
  Loop Until InStr( _
    elmNotificationText.GetCurrentPropertyValue(UIA_ValueValuePropertyId), _
    "ダウンロードが完了しました") > 0

  '[閉じる]ボタン押下
  Set iptn = elmCloseButton.GetCurrentPattern(UIA_InvokePatternId)
  iptn.Invoke
  '***** ダウンロード完了待ちここまで *****

  Exit Sub
Fin:
  MsgBox "処理が失敗しました。", vbCritical + vbSystemModal
End Sub

Private Function GetElement(ByVal uiAuto As CUIAutomation, _
                            ByVal elmParent As IUIAutomationElement, _
                            ByVal propertyId As Long, _
                            ByVal propertyValue As Variant, _
                            Optional ByVal ctrlType As Long = 0) As IUIAutomationElement
  Dim cndFirst As IUIAutomationCondition
  Dim cndSecond As IUIAutomationCondition

  Set cndFirst = uiAuto.CreatePropertyCondition( _
                   propertyId, _
                   propertyValue _
                 )
  If ctrlType <> 0 Then
    Set cndSecond = uiAuto.CreatePropertyCondition( _
                      UIA_ControlTypePropertyId, _
                      ctrlType _
                    )
    Set cndFirst = uiAuto.CreateAndCondition( _
                     cndFirst, _
                     cndSecond _
                   )
  End If
  Set GetElement = elmParent.FindFirst(TreeScope_Subtree, cndFirst)
End Function

IE関連

'********************************************************************************
' 関数名:GetIEObject
' 概要 :指定されたURLを開いているInternetExplorerのインスタンスを返します
' 引数 :[url]...URL
' 戻り値:InternetExplorerのインスタンス
'********************************************************************************
Public Function GetIEObject(ByVal url As String) As Object
    '戻り値を初期化します
    Set GetIEObject = Nothing

    'Shell.ApplicationのCOMをインスタンス化します
    Dim sh As Object
    Set sh = CreateObject("Shell.Application")

    '起動中のWindowを1つずつ調べます
    Dim w As Object
    For Each w In sh.Windows
        'InternetExplorerであれば
        If InStr(w.Name, "Internet Explorer") > 0 Then
            'かつ、指定されたURLを起動中であれば
            If (w.LocationURL = url) Then
                'そのインスタンスを戻り値となる変数にセットし、ループを抜けます
                Set GetIEObject = w
                Exit For
            End If
        End If
    Next
End Function


Option Explicit

'----------------------------------------
' Win32 API定義
'----------------------------------------
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

'Internet ExplorerのCOMをインスタンス化します
Dim ie As New InternetExplorer

Sub ログインページを開く()

    'サンプルHTMLを開いているInternet Explorerのインスタンスを取得します
    Set ie = GetIEObject("https://www.pairs.lv/")
    If (ie.LocationURL = "") Then
        ie.navigate "https://www.pairs.lv/"
        Exit Sub
    End If

    ie.Visible = Trsue

    Dim ancObj As HTMLAnchorElement
    For Each ancObj In ie.document.getElementsByClassName("login-facebook-button direct_btn")
        '当該ハイパーリンクを見つけたらクリックします
        ancObj.Click
        Exit For
    Next



End Sub
Sub FaceBookログインページのieセット()

    'Shell.ApplicationのCOMをインスタンス化します
    Dim sh As Object
    Set sh = CreateObject("Shell.Application")

    '起動中のWindowを1つずつ調べます
    Dim w As Object
    For Each w In sh.Windows
        'InternetExplorerであれば
        If (TypeOf w Is InternetExplorer) Then
            'かつ、指定のWebページを起動中であれば
            If (0 < InStr(w.LocationURL, "https://www.facebook.com/login")) Then
                'そのインスタンスを変数「ie」にセットし、ループを抜けます
                Set ie = w
                Exit For
            End If
        End If
    Next

    Dim inpObj As HTMLInputElement
    Set inpObj = ie.document.getElementById("email")
    inpObj.Value = ""

    Set inpObj = ie.document.getElementById("pass")
    inpObj.Value = ""

    Set inpObj = ie.document.getElementById("u_0_0")
    inpObj.Click

End Sub


Sub inputTest()

    Const targetURL As String = "https://lms.gacco.org/courses/course-v1:gacco+ga031+2019_10/courseware/572b7833ed5b4ba7983e5383fa5e4c8c/fc1b5aecd0304871a36f99f2aa73d7b6/"

    Dim ie As Object
    Set ie = GetIEObject(targetURL)
    If (ie.LocationURL = "") Then
        ie.Navigate targetURL
        Exit Sub
    End If

    ie.Visible = True

    Dim formElement As Object
    Set formElement = ie.document.getElementsByTagName("form")(0)

    Dim formElemChildren As Object
    Set formElemChildren = GetChildrenByTagname(formElement, "input select textarea")

    Dim element As Object
    For Each element In formElemChildren
        Select Case StrConv(element.tagName, vbLowerCase)
            Case "input"
                Select Case StrConv(element.Type, vbLowerCase)
                    Case "hidden"
                    Case "radio"
                        CheckByParentInnerText element, "01", include:=True
                    Case "text"
                        element.Value = "test"
                    Case "checkbox"
                        CheckByParentInnerText element, "02", include:=True
                    Case "submit"
                    Case Else
                End Select
            Case "select"
                SelectOptionByValueOrByInnerText element, "東京都"
            Case "textarea"
                element.Value = "test" & vbCrLf & "test"
            Case Else
        End Select
    Next


End Sub

Function GetChildrenByTagname(parentElement As Object, tagNamesSeparetedSpace As String, Optional ByRef elementCollection As Collection) As Object
    If elementCollection Is Nothing Then
        Set elementCollection = New Collection
    End If


    Dim tagNameArray As Variant, tagName As Variant
    tagNameArray = Split(tagNamesSeparetedSpace, " ")

    Dim element As Object, i As Long
    For Each element In parentElement.Children

        GetChildrenByTagname element, tagNamesSeparetedSpace, elementCollection

        For i = LBound(tagNameArray) To UBound(tagNameArray)
            If StrConv(element.tagName, vbLowerCase) = tagNameArray(i) Then
                elementCollection.Add element
            End If
        Next
    Next

    Set GetChildrenByTagname = elementCollection
End Function



Sub SelectOptionByValueOrByInnerText(selectElement As Object, valueOrInnerText As String)


    Dim optionEleCollec As Collection
    Set optionEleCollec = GetChildrenByTagname(selectElement, "option")

    Dim element As Object
    For Each element In optionEleCollec

        If element.Value = valueOrInnerText _
        Or element.innerText = valueOrInnerText Then

            element.Selected = True

        End If

    Next

End Sub


Sub CheckByParentInnerText(inputElement As Object, innerText As String, Optional include As Boolean = False)

    Dim checkFlg As Boolean
    checkFlg = False

    If include = True Then
        If InStr(inputElement.parentElement.innerText, innerText) > 0 Then
            checkFlg = True
        End If
    Else
        If inputElement.parentElement.innerText = innerText Then
            checkFlg = True
        End If
    End If

    inputElement.Checked = checkFlg
End Sub

タブキーによる選択の移動

Sub testtest()
    Dim ie As Object
    Set ie = CreateObject("InternetExplorer.Application")
    ie.Visible = True
    ie.navigate "about:blank"               'IE開く

    ie.navigate "http://synodos.jp/"    '指定のURLを開く

    'Internet ExplorerがURLを開けずにループし続ける場合を考慮し、制限時間を設けます
    'その前に、読み込み開始時間を記憶します
    Dim st As Date
    st = Now()

    Debug.Print st
    Debug.Print Format(st, "mmdd")

    '完全に開ききるまで待機します
    Do
        '開き終えたらループを抜けます
        If (ie.Busy = False) Then
            Exit Do
        End If

        '10秒経過してもInternet Explorerから処理が返ってこない場合は該当URLの読み込みを中断します
        If (DateAdd("s", 10, st) < Now()) Then
            Debug.Print "10秒以上経過したため、処理を中断します"
            ie.stop
            Exit Sub

        End If

        '1秒間待機します
        Sleep 1000

        '念のためタスクを開放します
        DoEvents
    Loop

    SetForegroundWindow ie.hwnd 'IEをアクティブに
    Application.Wait [Now()+”00:00:02”] '待機


    Dim obj As Object
    For Each obj In ie.document.getElementsByTagName("html") 'IEだとタブのフォーカスが最初はアドレスバーにあるから位置をhtmlに移動
        obj.Focus
        Exit For
    Next
    SendKeys "{TAB}{TAB}{TAB}"

End Sub

アップロードするファイルの選択

'----------------- API宣言部分 -----------------
Private Declare Function FindWindowEx Lib "user32.dll" _
    Alias "FindWindowExA" ( _
    ByVal hWndParent As Long, _
    ByVal hwndChildAfter As Long, _
    ByVal lpszClass As String, _
    ByVal lpszWindow As String) As Long

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
        (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr

Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" _
        (ByVal hwnd As Long, ByVal Msg As Long, _
        ByVal wParam As Long, ByVal lParam As Any) As Long

'Internet ExplorerのCOMをインスタンス化します
Dim ie As New InternetExplorer

Sub test()

  Dim hInputBox As Long
  Dim hButton As Long
  Dim hWindow As Long

'HWND FindWindow(
'  LPCTSTR lpClassName,  // クラス名
'  LPCTSTR lpWindowName  // ウィンドウ名
');

  hWindow = FindWindow("#32770", "アップロードするファイルの選択") '#32770は「ダイアログ」のクラス名

'HWND FindWindowEx(
'  HWND hwndParent,   // 親ウィンドウのハンドル
'  HWND hwndChildAfter,  // 子ウィンドウのハンドル
'  LPCTSTR lpszClass,   // クラス名
'  LPCTSTR lpszWindow   // ウィンドウ名
');

'入力ボックスについては幾つかのコントロールの入れ子になっているので、
'「ダイアログ」の中にある「ComboBoxEx32」の、更に中にある「ComboBox」の・・・
'といった様に順番に掘り下げていく必要があります。

'・親ウィンドウのハンドルは先ほど取得したダイアログのハンドルを指定します。
'・子ウィンドウのハンドルは無し。
hInputBox = FindWindowEx(hWindow, 0&, "ComboBoxEx32", "")

  hInputBox = FindWindowEx(hInputBox, 0&, "ComboBox", "")

'・入力ボックスのクラス名は「Edit」。ウィンドウ名は無し。
  hInputBox = FindWindowEx(hInputBox, 0&, "Edit", "")

'・ボタンのクラス名は「Button」。ウィンドウ名は「開く(&O)」となります。
  hButton = FindWindowEx(hWindow, 0&, "Button", "開く(&O)")

'ファイルパス入力'
Call SendMessage(hInputBox, &HC, 0, "C:\Users\Tom\Desktop\Excel遊び.xlsm")



'LRESULT SendMessage(
'  HWND hWnd,     // 送信先ウィンドウのハンドル
'  UINT Msg,       // メッセージ
'  WPARAM wParam,  // メッセージの最初のパラメータ
'  LPARAM lParam   // メッセージの 2 番目のパラメータ
');

'ボタン押下'
Call SendMessage(hButton, &H6, 1, 0&)  'ボタンをアクティブにする
Call SendMessage(hButton, &HF5, 0, 0&) 'ボタンをクリックする

End Sub

OutLook関連

Option Explicit

Sub sample()
    Dim outLookAp As Object
    Set outLookAp = CreateObject("Outlook.Application")


    Dim objItem As Object
    Dim objAttachment As Object
    Dim strFile As String
    Dim strPath As String

    strPath = "C:\Users\Tom\Documents\電子書籍\IT\プログラミング・スクリプト\Excel VBAクローリング&スクレイピング\Sample\3\tmp\tmp" 'ファイルを保存したいフォルダ

    Set objItem = outLookAp.ActiveInspector.CurrentItem '今開いているメールオブジェクトを取得
    For Each objAttachment In objItem.Attachments
        strFile = strPath & "\" & objAttachment.Filename
        objAttachment.SaveAsFile strFile
    Next

End Sub

Sub GetAllMail()
    Dim objOutlook As Outlook.Application
    Dim myNamespace As Outlook.Namespace
    Dim 受信トレイ As Object
    Dim mailFolder As Object

    Set objOutlook = New Outlook.Application
    Set myNamespace = objOutlook.GetNamespace("MAPI")

    Set 受信トレイ = myNamespace.GetDefaultFolder(olFolderInbox)

    Dim i As Long: i = 1 '出力用カウンタ
    Debug.Print 受信トレイ.Name
    メールを取得し、サブフォルダがあればそのメールも取得 受信トレイ, i

End Sub

Sub メールを取得し、サブフォルダがあればそのメールも取得(フォルダ As Object, ByRef mailCnt As Long)

    Dim i As Long
    If フォルダ.Items.Count > 0 Then
        For i = 1 To フォルダ.Items.Count
            mailCnt = mailCnt + 1
            With ThisWorkbook.Worksheets("Outlook")
                .Cells(mailCnt, 1).Value = フォルダ.Items(i).SentOn
                .Cells(mailCnt, 2).Value = フォルダ.Items(i).Subject
                .Cells(mailCnt, 3).Value = フォルダ.Items(i).Body
            End With
        Next i
    End If
    Dim mailFolder As Object
    For Each mailFolder In フォルダ.Folders
        Debug.Print mailFolder.Name
        メールを取得し、サブフォルダがあればそのメールも取得 mailFolder, i
    Next mailFolder
End Sub

ドラッグ&ドロップ関連

Private Sub ListView1_OLEDragDrop( _
    Data As MSComctlLib.DataObject, _
    Effect As Long, _
    Button As Integer, _
    Shift As Integer, _
    x As Single, _
    y As Single)

    Dim LineText As String
    Dim AllText As String
    Dim i

    If Data.Files.Count > 0 Then
        For i = 1 To Data.Files.Count
            MsgBox Data.Files(i)
        Next i
    End If
End Sub

クリップボード関連

Private Sub クリップボードの中身判定()
    Dim ClipBoard As Variant
    Dim i As Long

    ClipBoard = Application.ClipboardFormats

    If ClipBoard(1) = -1 Then
        MsgBox "クリップボードは空です。", vbExclamation
        Exit Sub
    End If

    For i = 1 To UBound(ClipBoard)
        MsgBox ClipBoard(i)
    Next i
End Sub

Private Sub クリップボードの中を見る()
    Dim CB As New DataObject
    CB.GetFromClipboard
    MsgBox CB.GetFormat(1)
sub
'https://staff.qualias.jp/technology/excel-vba-clipboard/




Public Function 提出期限(ByVal a_day As Date) As Date

    Dim day21later As Date
    day21later = a_day + 21

    Dim calender_array() As Variant
    calender_array = Calender.Range("カレンダー").Value
    Dim bisDayCnt As Long: bisDayCnt = 0
    Dim i As Long
    For i = UBound(calender_array) To LBound(calender_array) Step -1

        If day21later = calender_array(i, 1) Then

            Do
                If calender_array(i, 2) = 0 Then
                    bisDayCnt = bisDayCnt + 1

                    If bisDayCnt >= 2 Then Exit For

                End If

                i = i - 1

            Loop While i >= LBound(calender_array)
            Debug.Print "え!?"

        End If

    Next

    提出期限 = calender_array(i, 1)

End Function

自動実行

Excelマクロ自動実行サンプル
"C:\Program Files (x86)\Microsoft Office\root\Office16\EXCEL.EXE"
C:\Users\Tom\Documents\自作\自動実行\自動実行サンプル.xlsm /e

ピボットテーブル関連

Sub temp()
    Debug.Print Sheet_Table.ListObjects("売上表").Range.Address
    Debug.Print Sheet_Table.Range("売上表").Address
End Sub

Sub Macro1()
    '初期設定
    On Error Resume Next: Application.DisplayAlerts = False
        ThisWorkbook.Sheets("ピボットテーブル").Delete
    On Error GoTo 0: Application.DisplayAlerts = True

    Dim shPivot As Worksheet
    Set shPivot = CodeNameとシート名を指定してシートを作成("Sheet_PivotTable", "ピボットテーブル")

    Dim Lobj売上表 As ListObject
    Set Lobj売上表 = Sheet_Table.ListObjects("売上表")

    With ThisWorkbook.PivotCaches
        Dim pCache As PivotCache
        Set pCache = .Create(SourceType:=xlDatabase, SourceData:=Lobj売上表.Range, Version:=xlPivotTableVersion10)
    End With
    With pCache
        Dim pTable As pivotTable
        Set pTable = .CreatePivotTable(TableDestination:=shPivot.Cells(6, 3), TableName:="ピボットテーブルFrom売上表", DefaultVersion:=xlPivotTableVersion10)
    End With

    ピボットテーブルの行フィールド設定 pTable, Lobj売上表.HeaderRowRange.Cells(, 4).Value
    ピボットテーブルの列フィールド設定 pTable, Lobj売上表.HeaderRowRange.Cells(, 1).Value
    ピボットテーブルのデータフィールド設定 pTable, Lobj売上表.HeaderRowRange.Cells(, 8).Value
End Sub


Sub testChangeCodeName()
ChangeCodeName "sheet_test", "Sheet30"
End Sub
Public Sub ChangeCodeName(newCodeName As String, oldCodeName As String)
    ThisWorkbook.VBProject.VBComponents(oldCodeName).Properties("_CodeName") = newCodeName
End Sub

Sub test新しいシートをCodeNameを指定して追加()
CodeNameとシート名を指定してシートを作成 "Sheet_PivotTable", "ピボットテーブル"
End Sub
Function CodeNameとシート名を指定してシートを作成(newCodeName As String, newName As String) As Worksheet
    Dim newSheet As Worksheet
    With ThisWorkbook
        Set newSheet = .Sheets.Add(After:=.Sheets(.Sheets.Count))  'AddメソッドはAddしたシートを返す
    End With
    ChangeCodeName newCodeName, newSheet.CodeName
    newSheet.Name = newName
    Set CodeNameとシート名を指定してシートを作成 = newSheet
End Function

Sub ピボットテーブルの行フィールド設定(pTable As pivotTable, 項目名 As String)
    With pTable.PivotFields(項目名)
        .Orientation = xlRowField
        .Position = 1
    End With
End Sub
Sub ピボットテーブルの列フィールド設定(pTable As pivotTable, 項目名 As String)
    With pTable.PivotFields(項目名)
        .Orientation = xlColumnField
        .Position = 1
        .AutoGroup
    End With
End Sub
Sub ピボットテーブルのデータフィールド設定(pTable As pivotTable, 項目名 As String)
    With pTable
        .AddDataField .PivotFields(項目名), "合計 / 数量", xlSum
    End With
End Sub
Sub 折れ線グラフ()
    Dim obj As Shape
    Set obj = ActiveSheet.Shapes.AddChart2(227, xlLine)
    With obj.Chart
        .SetSourceData Source:=Sheet_PivotTable.Range("ピボットテーブル!$C$6:$G$21")
    End With
End Sub

配列関連

Sub データ一つ検証() 'セル一つのだとvar配列はエラーになる!
    Dim var配列() As Variant
    var配列 = Sheet_配列.Range("A1").Value
End Sub
Sub データ二つ検証() 'セル二つのだとvar配列はエラーにならない!⇒テーブルデータの場合は敢えてテーブルヘッダの行も入れるべき!
    Dim var配列() As Variant
    With Sheet_配列
        var配列 = .Range(Range("A1"), Range("A2")).Value
    End With
End Sub
Sub 日付列の日付データをdebugPrint()
    Const 日付ラベルセル番地 As String = "A1"
    Const ラベルの分 As Integer = 1
    Dim 日付配列() As Variant
    With Sheet_配列.Range(日付ラベルセル番地)
        If .End(xlDown).Row = .Parent.Rows.Count Then Exit Sub
        日付配列 = .Resize(.End(xlDown).Row - (.Row - ラベルの分), 1).Value
    End With
    Dim i As Long
    For i = LBound(日付配列) + ラベルの分 To UBound(日付配列)
        Debug.Print 日付配列(i, 1)
    Next
End Sub

非表示行削除

Sub 非表示行削除(sh As Worksheet)

    Application.ScreenUpdating = False '画面更新を停止
    Application.EnableEvents = False 'イベント発生を停止

    'Ctrl+Endによる移動
    Dim workRng As Range
    Set workRng = sh.Cells.SpecialCells(xlLastCell)

    '直後の可視セルに移動
    Do
        Set workRng = workRng.Offset(1)
    Loop While workRng.EntireRow.Hidden

    '行非表示セルをdelRows変数に格納
    Dim delRows As Range
    Do
        Set workRng = workRng.Offset(-1)
        If workRng.EntireRow.Hidden Then
            If delRows Is Nothing Then
                Set delRows = workRng
            Else
                Set delRows = Union(delRows, workRng)
            End If
        End If
    Loop Until workRng.Row = 1

    '行非表示セルがあったのなら非表示行を削除
    If Not delRows Is Nothing Then
        delRows.EntireRow.Delete
    End If

    Application.EnableEvents = True 'イベント発生再開
    Application.ScreenUpdating = True '画面更新再開

End Sub
Sub test非表示行削除()
非表示行削除 ActiveSheet
End Sub

日付関連

Function 文字列yyyymmddを日付に変換(str_yyyymmdd As String) As Date
    Dim work_str As String
    work_str = Format(str_yyyymmdd, "####/##/##") 'Format関数の"#"は数字1文字を表す
    If IsDate(work_str) Then
        文字列yyyymmddを日付に変換 = CDate(work_str)
    Else
        Debug.Print "引数不正(引数[" & str_yyyymmdd & "]がyyyymmdd形式でない)"
    End If
End Function
Sub test文字列yyyymmddを日付に変換()
Debug.Print 文字列yyyymmddを日付に変換("19911006")
End Sub

Function 文字列yyyymmddを引数n分前後させる(str_yyyymmdd As String, n As Long)
    Dim work_dt As Date
    work_dt = 文字列yyyymmddを日付に変換(str_yyyymmdd)
    work_dt = DateAdd("d", n, work_dt)
    文字列yyyymmddを引数n分前後させる = Format(work_dt, "yyyymmdd")
End Function
Sub test文字列yyyymmddを引数n分前後させる()
Debug.Print 文字列yyyymmddを引数n分前後させる("19910721", 10000)
End Sub

埋め込みグラフをセルに合わせる

Private Sub Worksheet_Change(ByVal Target As Range) 'セルの値が変更されたとき
    If Intersect(Target, Range("2:3")) Is Nothing Then
        Exit Sub
    Else
        MsgBox "セルの値が変更されました"
    End If
End Sub

Enum idx
    top = 0
    lef
    wid
    hei
End Enum

Sub ShapesFit()
    Dim myRange As Range
    Dim 位置と大きさ_外 As Variant, 位置と大きさ_内 As Variant
    位置と大きさ_外 = 位置と大きさを取得("外")
    位置と大きさ_内 = 位置と大きさを取得("内")

    Dim myShape As Shape
    Set myShape = ActiveSheet.Shapes("サンプルグラフ")
    Dim myChild As Variant
    myShape.Chart.SetSourceData Source:=Range("グラフ!$D$2:$G$3")
    With myShape
        .left = 位置と大きさ_外(idx.lef)
        .width = 位置と大きさ_外(idx.wid)
        .top = 位置と大きさ_外(idx.top)
        .Height = 位置と大きさ_外(idx.hei)
    End With
    With myShape.Chart
       Debug.Print .PlotArea.InsideLeft
       Debug.Print .PlotArea.InsideWidth
       Debug.Print .PlotArea.InsideTop
       Debug.Print .PlotArea.InsideHeight
        .PlotArea.InsideLeft = 位置と大きさ_内(idx.lef) - 位置と大きさ_外(idx.lef) - 4 '4は微調整
        .PlotArea.InsideWidth = 位置と大きさ_内(idx.wid)
        .PlotArea.InsideTop = 位置と大きさ_内(idx.top) - 位置と大きさ_外(idx.top) - 4
        .PlotArea.InsideHeight = 位置と大きさ_内(idx.hei)
       Debug.Print .PlotArea.InsideLeft
       Debug.Print .PlotArea.InsideWidth
       Debug.Print .PlotArea.InsideTop
       Debug.Print .PlotArea.InsideHeight
    End With
End Sub
Function 完全一致検索(検索値 As String) As Range
    Set 完全一致検索 = Cells.Find(What:=検索値, After:=Range("A1"), LookIn:=xlValues, LookAt:= _
            xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _
            , MatchByte:=False, SearchFormat:=False)
End Function

Function 位置と大きさを取得(内or外 As String) As Variant
    If Not (内or外 = "内" Or 内or外 = "外") Then
        MsgBox "設定エラー"
        Exit Function
    End If
    Dim Ret(4) As Variant

    Dim 左上Rng As Range, 右下Rng As Range
    Set 左上Rng = 完全一致検索("【左上(" & 内or外 & ")】")
    Set 右下Rng = 完全一致検索("【右下(" & 内or外 & ")】")
    Ret(idx.top) = 左上Rng.top
    Ret(idx.lef) = 左上Rng.left
    Ret(idx.wid) = 右下Rng.left + 右下Rng.width - 左上Rng.left
    Ret(idx.hei) = 右下Rng.top + 右下Rng.Height - 左上Rng.top
    位置と大きさを取得 = Ret
End Function

Outlook イベント操作

Microsoft Word Objects

Private Sub Document_Open()
    SetOutlookAppEvent
End Sub

標準モジュール

Module_AppEvent

Option Explicit

Private ObjOutlookAppEvent As New OutlookAppEvent

Public Sub SetOutlookAppEvent()
    Application.Visible = False
    Set ObjOutlookAppEvent = Nothing '2回以上呼び出す場合のため
    Set ObjOutlookAppEvent.App = CreateObject("Outlook.Application")
End Sub

クラスモジュール

OutlookAppEvent

Option Explicit

'-------------
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" _
        (ByVal hWnd As Long, ByVal lpsz0p As String, ByVal lpszFile As String, _
         ByVal lpszParams As String, ByVal lpszDir As String, _
         ByVal FsShowCmd As Long) As Long
'-------------

Public WithEvents App As Outlook.Application
Private ObjWordAppEvent As New WordAppEvent

Const TITLE = "test" ' 自動処理するメールの件名

Private Sub App_NewMailEx(ByVal EntryIDCollection As String)
    Dim arrEntryId() As String, objMail As Object, i As Long
    arrEntryId = Split(EntryIDCollection, ",")
    For i = LBound(arrEntryId) To UBound(arrEntryId)
        Set objMail = App.Session.GetItemFromID(arrEntryId(i))
        If InStr(objMail.Subject, TITLE) > 0 Then
            MsgBox "you got mail !"
            PrintAttachments objMail
        End If
    Next
End Sub

Private Sub App_Quit()
    Dim setTime As Date
    setTime = Now + TimeValue("00:00:05")  '5秒後に実行
    Application.OnTime setTime, "SetOutlookAppEvent"
End Sub

Private Sub App_Startup()
'OutlookAppEventクラスのオブジェクトの中にThisDocumentを扱うWordを格納することで、
'他のWordを起動したときにそのWordもInvisibleになってしまうのを防止することに成功した。
    Set ObjWordAppEvent = Nothing
    Set ObjWordAppEvent.App = GetObject(ThisDocument.FullName).Parent
    ObjWordAppEvent.App.Visible = False
End Sub

Public Sub PrintAttachments(ByVal objMail As MailItem)
MsgBox "PrintAttachments関数を呼び出しました"
    Const ATTACH_PATH = "C:\Users\Tom\Desktop\"   ' 添付ファイルを保存するフォルダを指定

    Dim objAttach As Attachment
    Dim strFileName As String
MsgBox "添付ファイル数:" & objMail.Attachments.Count
    If objMail.Attachments.Count > 0 Then
        For Each objAttach In objMail.Attachments
            ' 添付ファイルを指定フォルダに保存
            strFileName = ATTACH_PATH & objAttach.FileName
MsgBox strFileName & "を保存します"
            objAttach.SaveAsFile strFileName
            ' 保存したファイルを印刷する
'            Call ShellExecute(0, "print", strFileName, 0, ATTACH_PATH, 0)
        Next
    Else
    End If

End Sub

WordAppEventWordAppEvent

Option Explicit

Public WithEvents App As Word.Application

Private Sub App_WindowActivate(ByVal Doc As Document, ByVal Wn As Window)
    App.Visible = False
End Sub

Private Sub App_WindowDeactivate(ByVal Doc As Document, ByVal Wn As Window)
    App.Visible = False
End Sub

Private Sub App_WindowSelectionChange(ByVal Sel As Selection)
    App.Visible = False
End Sub

image.png

ハッシュ値

Sub testGetFileHashMD5()
Debug.Print GetFileHashMD5("C:\Users\Tom\Desktop\test.txt") 'OK
Debug.Print GetFileHashMD5("C:\Users\Tom\Desktop\1Byte.txt") 'OK
Debug.Print GetFileHashMD5("C:\Users\Tom\Desktop\null.txt") '空文字列を返す
End Sub

' 指定したファイルの MD5 ハッシュ値を取得する
Function GetFileHashMD5(fullName As String) As String

    'ハッシュ値作成
    Dim ByteArrayFromBinary
    ByteArrayFromBinary = ReadFileAsBinary(fullName)
    If VarType(ByteArrayFromBinary) <= vbNull Then Exit Function
    Dim md5
    Set md5 = CreateObject("System.Security.Cryptography.MD5CryptoServiceProvider")
    md5.ComputeHash_2 (ByteArrayFromBinary)
    Dim hashed_16() As Byte
    hashed_16 = md5.hash

    'ハッシュ値文字列化
    Dim msxml
    Set msxml = CreateObject("MSXML2.DOMDocument")
    Dim xmlElement
    Set xmlElement = msxml.CreateElement("tmp")
    xmlElement.DataType = "bin.hex"
    xmlElement.NodeTypedValue = hashed_16
    GetFileHashMD5 = xmlElement.Text
End Function

'指定したファイルのByte型配列を返却する
Function ReadFileAsBinary(fullName As String)
    Const adTypeBinary = 1
    Dim stm
    Set stm = CreateObject("ADODB.Stream")
    stm.Type = adTypeBinary
    stm.Open
    stm.LoadFromFile fullName
    ReadFileAsBinary = stm.Read
End Function
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2