1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?