ラベル vba の投稿を表示しています。 すべての投稿を表示
ラベル vba の投稿を表示しています。 すべての投稿を表示

2019年10月4日金曜日

シート保護掛けたが、パスワードを忘れてしまいました?ハッキング方法

下記のソースコードを解除したいシートにコピーして、実行するだけ…
Sub PasswordBreaker()
Dim i As Integer, j As Integer, k As Integer
Dim l As Integer, m As Integer, n As Integer
Dim i1 As Integer, i2 As Integer, i3 As Integer
Dim i4 As Integer, i5 As Integer, i6 As Integer
On Error Resume Next
For i = 65 To 66: For j = 65 To 66: For k = 65 To 66
For l = 65 To 66: For m = 65 To 66: For i1 = 65 To 66
For i2 = 65 To 66: For i3 = 65 To 66: For i4 = 65 To 66
For i5 = 65 To 66: For i6 = 65 To 66: For n = 32 To 126
ActiveSheet.Unprotect Chr(i) & Chr(j) & Chr(k) & _
Chr(l) & Chr(m) & Chr(i1) & Chr(i2) & Chr(i3) & _
Chr(i4) & Chr(i5) & Chr(i6) & Chr(n)
If ActiveSheet.ProtectContents = False Then
MsgBox "One usable password is " & Chr(i) & Chr(j) & _
Chr(k) & Chr(l) & Chr(m) & Chr(i1) & Chr(i2) & _
Chr(i3) & Chr(i4) & Chr(i5) & Chr(i6) & Chr(n)
Exit Sub
End If
Next: Next: Next: Next: Next: Next
Next: Next: Next: Next: Next: Next
End Sub
ここ参照

2019年7月2日火曜日

2019年7月1日月曜日

vlookupではできない、範囲指定のカスタマイズ関数

Function vlookups(val As Range, min As Range, max As Range, col As Range) As String
Dim cl As Range
For Each cl In min
    If val.Value >= cl.Value And val.Value <= cl.Worksheet.Cells(cl.Row, max.Column) Then
        vlookups = cl.Worksheet.Cells(cl.Row, col.Column)
        Exit For
    End If
Next
End Function
使い方: =vlookups(E4,$A$1:$A$4,$B$1:$B$4,$C$1:$C$4) 結果:

2019年5月10日金曜日

令和数式を置換してくれる自作関数

ポイントは正規表現のReplaceで、パターン化して一致されたセルの番地を更にReplaceに使ったこと。「$1」を使って一個目のマッチングを引用すること。
Option Explicit
Public Const REIWA = "IF(_CELL_>=DATE(2019,5,1),""令和""&IF(YEAR(_CELL_)-2018=1,""元"",YEAR(_CELL_)-2018)&""年""&MONTH(_CELL_)&""月""&DAY(_CELL_)&""日"",TEXT(_CELL_,""ggge年m月d日""))"
Function reiwa_switch(strFormual, strCellAddr As String) As String

Dim reg As Object
Set reg = CreateObject("VBScript.RegExp")
With reg
    .Pattern = "TEXT\((" & strCellAddr & "),""ggge年m月d日""\)"
    .IgnoreCase = False
    .Global = True
End With
reiwa_switch = reg.Replace(strFormual, Replace(REIWA, "_CELL_", "$1"))
End Function

=reiwa_switch(A1,A2)→関数


TEXT(data!FU3,"ggge年m月d日")→第一引数(A1)
data!FU3→第二引数(A2)
IF(data!FU3>=DATE(2019,5,1),"令和"&IF(YEAR(data!FU3)-2018=1,"元",YEAR(data!FU3)-2018)&"年"&MONTH(data!FU3)&"月"&DAY(data!FU3)&"日",TEXT(data!FU3,"ggge年m月d日"))→結果

2018年8月2日木曜日

複数PDFを一括印刷する、PDF毎の一枚目は飛ばす。ドラッグアンドドロップ

'//Bath Print multiple pdfs without the first page
'//複数PDFを一括印刷する、PDF毎の一枚目は飛ばす。ドラッグアンドドロップでできます

set WshShell = CreateObject ("Wscript.Shell")
set fs = CreateObject("Scripting.FileSystemObject")
Set objArgs = WScript.Arguments

if objArgs.Count < 1 then
msgbox("Please drag a file on the script")
WScript.quit
end if

Set gApp = CreateObject("AcroExch.App")
gApp.show '<- br="" comment="" hidden="" in="" mod="" or="" out="" take="" to="" work=""> 

'open via Avdoc and print
for i=0 to objArgs.Count - 1
FileIn = ObjArgs(i)
Set AVDoc = CreateObject("AcroExch.AVDoc")
If AVDoc.Open(FileIn, "") Then
Set PDDoc = AVDoc.GetPDDoc()
Set JSO = PDDoc.GetJSObject
x = PDDoc.GetNumPages
jso.print false, 1, x-1, true
gApp.CloseAllDocs
end if
next

gApp.hide : gApp.exit : Quit()
MsgBox "Done!"

Sub Quit
Set JSO = Nothing : Set PDDoc = Nothing : Set gApp =Nothing : Wscript.quit
End Sub

2018年6月29日金曜日

同じ時刻じゃないの?!!という罠


?cdate("2014/01/02 16:05:00") = dateadd("n",5,cdate("2014/01/02 16:00:00"))
False
?cdate("2014/01/02 16:05:00") - dateadd("n",5,cdate("2014/01/02 16:00:00"))
7.27595761418343E-12

おかしいでしょう! 16:05:00は16:00:00に5分足すじゃない!
参考ここ:
https://www.reddit.com/r/vba/comments/5mdnpb/pic_of_my_data_mismatch_problem/
http://www.fmsinc.com/tpapers/math/index.html

DateDiff("s", cdate("2014/01/02 16:05:00"), dateadd("n",5,cdate("2014/01/02 16:00:00"))) = 0


2017年9月7日木曜日

「_xlfn.IFERROR」という #NAME?エラー見えない「名前定義」にエラーがあった場合

下記の王なメソッドを作って、一旦エラーになっている名前定義を見える化にして、そして「名前」一覧から手動で削除して、ブックを保存
Sub delErrNames()
Dim n As name
Dim bk As Workbook
Set bk = ThisWorkbook

For Each n In bk.Names
    If n.RefersTo = "=#NAME?" Then
      n.Visible = True
    End If
Next
End Sub

2017年6月9日金曜日

GHOST BREAKPOINT,VBA ブレークポイント設置してないのに、急にいちいち止まるようになる件

解決方法
1.Debugに入って(そもそも止まらないなら、とりあえずなんかのsubを作成して、PBを置いて止める)
2.Ctrl+Pauseを2回押す
3.Playで継続
4.保存

2017年4月27日木曜日

PHONETIC関数が効かない時

PHONETICという漢字をカタカナに変換してくれる関数があります。しかし何故か変換せれず漢字のまま出力されてしまう時があります。
その時は、マクロのチカラを借りる。
例えば漢字の列がA列の場合:

Range("A:A").SetPhonetic

実行後、隣の列で「=PHONETIC("A1")」で数式を入れると変換されます

2017年3月30日木曜日

ListBoxがマウスのスクロール対応していない?!

やってみたら本当だ。
幸いソリューションは既にありました。ありがとうございます。
参照: https://social.msdn.microsoft.com/Forums/en-US/7d584120-a929-4e7c-9ec2-9998ac639bea/mouse-scroll-in-userform-listbox-in-excel-2010?forum=isvvba
Private Sub ListBox1_MouseMove( _
             ByVal Button As Integer, ByVal Shift As Integer, _
             ByVal x As Single, ByVal y As Single)
' start tthe hook
     HookListBoxScroll
End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
     UnhookListBoxScroll
End Sub
''''''' end Userform code

''''''' normal module code
Option Explicit

Private Type POINTAPI
     x As Long
     y As Long
End Type

Private Type MOUSEHOOKSTRUCT
     pt As POINTAPI
     hwnd As Long
     wHitTestCode As Long
     dwExtraInfo As Long
End Type

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

Private Declare Function GetWindowLong Lib "user32.dll" _
                     Alias "GetWindowLongA" ( _
                             ByVal hwnd As Long, _
                             ByVal nIndex As Long) As Long

Private Declare Function SetWindowsHookEx Lib "user32" _
                     Alias "SetWindowsHookExA" ( _
                             ByVal idHook As Long, _
                             ByVal lpfn As Long, _
                             ByVal hmod As Long, _
                             ByVal dwThreadId As Long) As Long

Private Declare Function CallNextHookEx Lib "user32" ( _
                             ByVal hHook As Long, _
                             ByVal nCode As Long, _
                             ByVal wParam As Long, _
                             lParam As Any) As Long

Private Declare Function UnhookWindowsHookEx Lib "user32" ( _
                             ByVal hHook As Long) As Long

Private Declare Function PostMessage Lib "user32.dll" _
                     Alias "PostMessageA" ( _
                             ByVal hwnd As Long, _
                             ByVal wMsg As Long, _
                             ByVal wParam As Long, _
                             ByVal lParam As Long) As Long

Private Declare Function WindowFromPoint Lib "user32" ( _
                             ByVal xPoint As Long, _
                             ByVal yPoint As Long) As Long

Private Declare Function GetCursorPos Lib "user32.dll" ( _
                             ByRef lpPoint As POINTAPI) As Long

Private Const WH_MOUSE_LL As Long = 14
Private Const WM_MOUSEWHEEL As Long = &H20A
Private Const HC_ACTION As Long = 0
Private Const GWL_HINSTANCE As Long = (-6)

Private Const WM_KEYDOWN As Long = &H100
Private Const WM_KEYUP As Long = &H101
Private Const VK_UP As Long = &H26
Private Const VK_DOWN As Long = &H28
Private Const WM_LBUTTONDOWN As Long = &H201

Private mLngMouseHook As Long
Private mListBoxHwnd As Long
Private mbHook As Boolean

Sub HookListBoxScroll()
Dim lngAppInst As Long
Dim hwndUnderCursor As Long
Dim tPT As POINTAPI
        GetCursorPos tPT
        hwndUnderCursor = WindowFromPoint(tPT.x, tPT.y)
        If mListBoxHwnd <> hwndUnderCursor Then
             UnhookListBoxScroll
             mListBoxHwnd = hwndUnderCursor
                lngAppInst = GetWindowLong(mListBoxHwnd, GWL_HINSTANCE)
                PostMessage mListBoxHwnd, WM_LBUTTONDOWN, 0&, 0&
             If Not mbHook Then
                     mLngMouseHook = SetWindowsHookEx( _
                                                     WH_MOUSE_LL, AddressOf MouseProc, lngAppInst, 0)
                     mbHook = mLngMouseHook <> 0
             End If
     End If
End Sub

Sub UnhookListBoxScroll()
     If mbHook Then
             UnhookWindowsHookEx mLngMouseHook
             mLngMouseHook = 0
             mListBoxHwnd = 0
             mbHook = False
     End If
End Sub

Private Function MouseProc( _
             ByVal nCode As Long, ByVal wParam As Long, _
             ByRef lParam As MOUSEHOOKSTRUCT) As Long
        On Error GoTo errH 'Resume Next
        If (nCode = HC_ACTION) Then
             If WindowFromPoint(lParam.pt.x, lParam.pt.y) = mListBoxHwnd Then
                     If wParam = WM_MOUSEWHEEL Then
                             MouseProc = True
                             If lParam.hwnd > 0 Then
                                     PostMessage mListBoxHwnd, WM_KEYDOWN, VK_UP, 0
                             Else
                                     PostMessage mListBoxHwnd, WM_KEYDOWN, VK_DOWN, 0
                             End If
                             PostMessage mListBoxHwnd, WM_KEYUP, VK_UP, 0
                             Exit Function
                     End If
             Else
                     UnhookListBoxScroll
             End If
     End If
        MouseProc = CallNextHookEx( _
                             mLngMouseHook, nCode, wParam, ByVal lParam)
     Exit Function
errH:
        UnhookListBoxScroll
End Function

2017年3月15日水曜日

VBA DLL を正しく呼び出せません (エラー 49)

SubもFunctionもパラメーターの前にByValかByRefかをきちんと書こう!

2017年2月15日水曜日

VBA Arrayの論理計算、交集、並集(AND OR)(Intersection And Union)(Logical disjunction Logical conjunction)

Option Explicit
Sub testUnionAndIntersection()

'Intersection And Union
'Also called
'Logical disjunction Logical conjunction
'AND OR

Dim a As New Scripting.Dictionary
Dim b As New Scripting.Dictionary
Dim keysA As Variant
Dim keysB As Variant
Dim keysC As Variant
Dim keysD As Variant

a.Add "A", ""
a.Add "B", ""
a.Add "C", ""

b.Add "A", ""
b.Add "C", ""
b.Add "X", ""

keysA = a.Keys
keysB = b.Keys

keysC = getIntersectionSet(keysA, keysB)
Debug.Print Join(keysC, ",")
'A,C

keysD = getUnionSet(keysA, keysB)
Debug.Print Join(keysD, ",")
'A,B,C,X

Call DeleteElementAt(1, keysB)
Debug.Print Join(keysB, ",")
'A,X

End Sub
Function getIntersectionSet(arr1 As Variant, arr2 As Variant) As Variant
Dim vntTmp As Variant
Dim vntRst As Variant

If Not (IsArray(arr1) And IsArray(arr2)) Then
    Exit Function
End If

For Each vntTmp In arr1
    If IsInArray(CStr(vntTmp), arr2) Then
        push vntTmp, vntRst
    End If
Next

getIntersectionSet = vntRst

End Function
Function getUnionSet(arr1 As Variant, arr2 As Variant) As Variant
Dim vntTmp As Variant
Dim vntRst As Variant

If Not (IsArray(arr1) And IsArray(arr2)) Then
    Exit Function
End If

vntRst = arr1

For Each vntTmp In arr2
    If Not IsInArray(CStr(vntTmp), vntRst) Then
        push vntTmp, vntRst
    End If
Next

getUnionSet = vntRst

End Function
Function IsInArray(stringToBeFound As String, arr As Variant) As Boolean
  IsInArray = (UBound(Filter(arr, stringToBeFound)) > -1)
End Function
Public Sub DeleteElementAt(ByVal index As Integer, ByRef prLst As Variant)
       Dim i As Integer
        For i = index + 1 To UBound(prLst)
            prLst(i - 1) = prLst(i)
        Next
        ReDim Preserve prLst(UBound(prLst) - 1)
End Sub

Public Function push(ByVal val As Variant, ByRef arr As Variant, Optional ByVal unique As Boolean = False) As Integer
Dim lngX As Long
    If unique Then
        If Not IsEmpty(arr) Then
            If IsArray(arr) Then
                For lngX = LBound(arr) To UBound(arr)
                    If arr(lngX) = val Then
                        push = UBound(arr)
                        Exit Function
                    End If
                Next
            End If
        End If
    End If
    If IsArray(arr) Then
        On Error GoTo initArray
        ReDim Preserve arr(UBound(arr) + 1)
    Else
initArray:
        ReDim arr(0)
    End If
    If VarType(val) = 9 Then '9 is object
        Set arr(UBound(arr)) = val
    Else
        arr(UBound(arr)) = val
    End If
    push = UBound(arr)
End Function


2016年12月6日火曜日

ADOレコーダーがあるのに、RecordCountが「-1」の場合の対処

レコーダーがあるのに、RecordCountが「-1」の場合の対処

connect.CursorLocation = 3 'クライアントカーソルにする
Set rs = execQuery(cn, sql, , adOpenKeyset, adLockOptimistic)
debug.print rs.RecordCount

2016年9月2日金曜日

列の値を一括更新(LOOP、Query、補助列を使わず!)

列の値を一括更新するときは、vbaで行ごとLOOPを書くか、ADODBでUpdateクエリーを書くか、補助列を挿入して数式で計算させるかでも、最近「Evaluate」知ったですよ

Range("B:B").Value = Evaluate(Range("B:B").Address & "*10")

これは神メソッドですね。気を付けなければならないのは、空欄が0に評価されてしまう、数字以外の文字列がエラーになる。

メソッド化にすると
Sub updateRangeValues(ByRef rg As Range, strFormula As String, Optional strFormat As String = "")
    rg.Worksheet.Activate '←ここが重要!!、なぜかこうしないと全部0と評価してしまう
    If strFormat <> "" Then
        rg.NumberFormatLocal = strFormat
    End If
    rg.Value = Application.Evaluate(rg.Address & strFormula)
    Application.Calculate
    Do While Application.CalculationState <> xlDone '←念のため、計算が終わまでDoEvents
        DoEvents
    Loop
End Sub
使い方:

Call updateRangeValues(Range("A1:A1000"),"*10.1","#.00")

LOOP、Query、補助列を使わずに、"A1:A1000"列の数値を全部*10.1,書式を小数点二桁にする


もう少し複雑な数式でもいけるらしい
Sub nn()
Dim rg As Range
Set rg = ThisWorkbook.Worksheets(1).Range("C1:C36")
strFormula = "=IF(" & rg.Address & "= """",""IS EMPTY""," & rg.Address & "*10)"
rg.Value = Application.Evaluate(strFormula)
End Sub

2016年7月15日金曜日

ado,sqlのunderline…自分かバカすぎで笑えない

sqlではアンダーライン"_"は、任意の一文字って意味か、ADOでもMysqlでも...、やられた、ADOでは"[]"でエスケープする、sqlでは"\"でエスケープする。
正規表現とごっちゃまぜしちゃダメよ。(;_;)


SELECT * FROM tbl WHERE tname LIKE 'abc[_]%'

SQL

SELECT * FROM tbl WHERE tname LIKE 'abc\_%'

2016年6月30日木曜日

VBAのRoundの罠

ROUND(38.5)
結果:38

ROUND(39.5)
結果:40

「銀行家の丸め (bankers' rounding)」、「銀行丸め」ともいう。
5が切り捨てられたり切り上げられたりするので「五捨五入」と呼ばれたり、
端数がちょうど0.5の場合に整数部分が偶数なら切り捨て奇数なら切り上げる
ので「偶捨奇入」と呼ばれたりもする。



本当の「四捨五入」したい場合は

WorksheetFunction.Round()

が有効だそうです。
しかし、ADODB,Jet.OLEDBなどでQuery(クエリー)で運用時は使えないので

sql = "UPDATE MyTable SET `Ammount` = ROUND(35*1.1)"
Call csv_cn.Execute(sql)

=ROUND(38.5) = 38



sql = "UPDATE MyTable SET `Ammount` = FORMAT(35*1.1,""#"")"
Call csv_cn.Execute(sql)

=ROUND(38.5) = 39

ちなみに、小数点以下2位の四捨五入は

sql = "UPDATE MyTable SET `Ammount` = FORMAT(35*1.111,""#.00"")"
Call csv_cn.Execute(sql)




2016年6月24日金曜日

Scripting.Dictionaryのkeyまたはitemをindexで参照する方法

Dim dic As New Scripting.Dictionary
dic.Add "a", "apple"
dic.Add "b", "banana"

'For Eachで
Dim vntKey As Variant
For Each vntKey In dic.Keys
    Debug.Print vntKey & ":" & dic(vntKey)
Next

'または Forで
Dim intX As Integer
For intX = 0 To dic.Count - 1
    Debug.Print dic.Keys(intX) & ":" & dic.Items(intX)
Next


'Indexで指定でもいい←これは面白い
Debug.Print dic.Keys()(0) & ":" & dic.Items()(0)
Debug.Print dic.Keys()(1) & ":" & dic.Items()(1)
'最後のkeyとvalue
Debug.Print dic.Keys()(dic.Count - 1) & ":" & dic.Items()(dic.Count - 1)

2014年11月7日金曜日

エクセルで右クリックが効かないときの対策

エクセルで右クリックが効かないときの対策
①エクセルを開いて
②Alt + F11押してVBEを出します
③Ctrl+Gでイミディエイトを出します
④下記をコピペして、Enterを押す

Application.CommandBars("cell").Enabled = True

⑤Alt+Qでシートに戻る

シートタブの右クリックが無効になった場合の対策
方法はほぼ同じ、④番のコピペが下記に変更するだけ

Application.CommandBars("Ply").Enabled = True

2014年10月30日木曜日

VBAでクエリーが日本語を含めると結果が文字化ける件

Sub hh()
Dim sql As String
Dim rs As New ADODB.Recordset
Dim con As ADODB.Connection
Dim dbConnStr As String
dbConnStr = "Driver={MySQL ODBC 5.2 ANSI DRIVER}; SERVER=localhost; DATABASE=landscape; USER=root; PASSWORD=mypass;"
Set con = New ADODB.Connection
con.Open dbConnStr
sql = "SELECT '東京都' AS tokyou"
rs.Open sql, con
Debug.Print rs!tokyou
rs.Close
Set rs = Nothing
con.Close
Set con = Nothing
End Sub
結果表示

東・

ここでは「Driver={MySQL ODBC 5.2 ANSI DRIVER}」を「Driver={MySQL ODBC 5.2 UNICODE DRIVER}」に変更すればOK
また、「rs!tokyou」は「rs.Fields("tokyou")」で書いたほうがいいと思います。