I dispose a macro tool that I used for the distance calculation between different points in Excel. However since Google API started billing the service it is out of use.
I have created a google API key but for the moment I am stuck at this step, it says that the method open of the object 'IXMLHTTPRequest' has failed
https://i.stack.imgur.com/ODXT4.png
https://i.stack.imgur.com/6ZDcG.png
Could you please help me on that?
Here is the entire script of my macro:
Sub Calculer(Départ As String, Arrivée As String, Distance As String, Temps As Double)
Dim surl As String
Dim oXH As Object
Dim bodytxt As String
'Utilisation de l'API Google
Distance = ""
Temps = 0
Départ = Replace(Départ, " ", "+")
Départ = SupprimerAccents(Départ)
Arrivée = Replace(Arrivée, " ", "+")
Arrivée = SupprimerAccents(Arrivée)
surl = "http://maps.googleapis.com/maps/api/distancematrix/xml?origins=" & _
Départ & "&destinations=" & Arrivée & _
"&mode=driving&sensor=false&units=metric"
Set oXH = CreateObject("msxml2.xmlhttp")
With oXH
.Open "get", surl, False
.send
bodytxt = .responseText
End With
bodytxt = Right(bodytxt, Len(bodytxt) - InStr(1, bodytxt, "<text>") - 5)
If InStr(1, bodytxt, "</text>") <> 0 Then Temps_Texte = Left(bodytxt, InStr(1, bodytxt, "</text>") - 1)
If Temps_Texte <> "" Then
Temps_Texte = Replace(Temps_Texte, " weeks", "w")
Temps_Texte = Replace(Temps_Texte, " week", "w")
Temps_Texte = Replace(Temps_Texte, " day", "j")
Temps_Texte = Replace(Temps_Texte, " hours", "h")
Temps_Texte = Replace(Temps_Texte, " hour", "h")
Temps_Texte = Replace(Temps_Texte, " mins", "m")
Temps_Texte = Replace(Temps_Texte, " min", "m")
Temps_Texte = Replace(Temps_Texte, " seconds", "s")
Temps_Texte = Replace(Temps_Texte, " second", "s")
Heure = Split(Temps_Texte, " ")
j = 0
On Error GoTo fin
If Right(Heure(j), 1) = "w" Then Temps = Temps + Val(Heure(j)) * 7: j = j + 1
If Right(Heure(j), 1) = "d" Then Temps = Temps + Val(Heure(j)): j = j + 1
If Right(Heure(j), 1) = "h" Then Temps = Temps + Val(Heure(j)) / 24: j = j + 1
If Right(Heure(j), 1) = "m" Then Temps = Temps + Val(Heure(j)) / 24 / 60: j = j + 1
If Right(Heure(j), 1) = "s" Then Temps = Temps + Val(Heure(j)) / 24 / 60 / 60: j = j + 1
fin:
On Error GoTo 0
End If
bodytxt = Right(bodytxt, Len(bodytxt) - InStr(1, bodytxt, "<text>") - 5)
If InStr(1, bodytxt, "</text>") <> 0 Then Distance = Left(bodytxt, InStr(1, bodytxt, "</text>") - 1)
If Distance = "" Then Distance = "Aucun résultat"
Distance = Replace(Distance, " km", "")
Distance = Replace(Distance, ",", "")
Set oXH = Nothing
End Sub
Function SupprimerAccents(ByVal sChaine As String) As String
'Fonction récupérée ici : http://www.developpez.net/forums/d1089902/logiciels/microsoft-office/excel/macros-vba-excel/suppression-accents-chaines-caracteres/
Dim sTmp As String, i As Long, p As Long
Const sCarAccent As String = "ÁÂÃÄÅÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïñòóôõöùúûüýÿ"
Const sCarSansAccent As String = "AAAAACEEEEIIIINOOOOOUUUUYaaaaaaceeeeiiiinooooouuuuyy"
sTmp = sChaine
For i = 1 To Len(sTmp)
p = InStr(sCarAccent, Mid(sTmp, i, 1))
If p > 0 Then Mid$(sTmp, i, 1) = Mid$(sCarSansAccent, p, 1)
Next i
SupprimerAccents = sTmp
End Function
In this line:
surl = "http://maps.googleapis.com/maps/api/distancematrix/xml?origins=" & _
Départ & "&destinations=" & Arrivée & _
"&mode=driving&sensor=false&units=metric"
Add your key (and remove the &sensor=false):
surl = "http://maps.googleapis.com/maps/api/distancematrix/xml?origins=" & _
Départ & "&destinations=" & Arrivée & _
"&mode=driving&units=metric&key=MY_API_KEY"
Related
There are some good posts that describe the two major ways of measuring the performance of your code. However, if you have a multi-module project with calls that may execute thousands of sub routine calls at a single operation, it is difficult to pin down where the performance hogs are. How to come about this?
I did write a generic benchmarking code that can be added to any vba project. It works by adding code to each entry and exit point of every sub/function/property to measure the time spent in each sub both as total time as well as time excluding sub-subroutines. This is how to use it:
Create a new module in your project called modBench. Naming is
important.
Copy the code shown below to that module.
Make sure that Microsoft Visual Basic for Application Extensability
is referenced in VBA
Make sure that you allow excel to allow "Trust access to the VBA
project object model" (excel setting in Options=>Trust Center=>Trust
Center Settings=>Macro Settings
Your workbook should be saved as a different name
Run "Start_Benchmark"
Do some tasks. Avoid msg-boxes and similar to show real "cpu-hogs"
Run "End_Benchmark"
A report is generated in the same folder as the workbook.
Code of module "modBench":
Option Explicit
Private Const CLT_1 = " 'CODE INSERTED BY MODBENCH"
Private Const CLT_2 = """ INSERTED BY MODBENCH"
Private Const CLT_3 = " 'PARTIAL CODE """
Private Const CLT_4 = "'MODBENCH TO INSERT PROCEDURE INFO START HERE"
Public Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As Currency) As Long
Public Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As Currency) As Long
Private p_count(10000) As Long
Private p_total_time(10000) As Currency
Private p_module_time(10000) As Currency
Private p_in_time(10000) As Currency
Private p_call_stack(10000) As Long
Private p_call_stack_indx As Long
Private t1 As Currency
Private t2 As Currency
Sub PrintBenchResults()
Dim i As Long, j As Long, dTimerTmp() As Double, lMaxIndx As Long
Dim m_PerfFrequency As Currency
QueryPerformanceFrequency m_PerfFrequency
ReDim dTimerTmp(UBound(dTimer))
For i = 0 To UBound(dTimerTmp)
dTimerTmp(i) = dTimer(i) / m_PerfFrequency * 1000
Next
Do
lMaxIndx = 0
For i = 1 To UBound(dTimerTmp)
If dTimerTmp(i) > dTimerTmp(lMaxIndx) Then lMaxIndx = i
Next
If dTimerTmp(lMaxIndx) < -1000 Then Exit Do
If lCount(lMaxIndx) > 0 Then
Debug.Print Round(dTimerTmp(lMaxIndx), 1) & " ms (" & lCount(lMaxIndx) & " runs) " & vbTab & Round(dTimerTmp(lMaxIndx) / lCount(lMaxIndx), 3) & " ms per run" & vbTab & sProc(lMaxIndx)
Else
Debug.Print Round(dTimerTmp(lMaxIndx), 3) & " ms (" & lCount(lMaxIndx) & " runs) " & vbTab & sProc(lMaxIndx)
End If
dTimerTmp(lMaxIndx) = -1001
Loop
End Sub
Sub p_out(P_id As Long)
Dim time_out As Currency
QueryPerformanceCounter time_out
p_call_stack_indx = p_call_stack_indx - 1
t1 = time_out - p_in_time(p_call_stack_indx)
p_total_time(P_id) = p_total_time(P_id) + t1
p_module_time(P_id) = p_module_time(P_id) + t1
If p_call_stack_indx > 0 Then
p_module_time(p_call_stack(p_call_stack_indx - 1)) = p_module_time(p_call_stack(p_call_stack_indx - 1)) - t1
End If
End Sub
Sub p_in(P_id As Long)
Dim time_in As Currency
QueryPerformanceCounter time_in
p_in_time(p_call_stack_indx) = time_in
p_call_stack(p_call_stack_indx) = P_id
p_call_stack_indx = p_call_stack_indx + 1
p_count(P_id) = p_count(P_id) + 1
End Sub
Sub Start_Benchmark()
Dim VBComp As VBIDE.VBComponent, ThisModule As VBIDE.CodeModule, i As Long, j As Long, ProcStartOffset As Long
Dim p_index As Long
Dim ProcedureKind As Long
Dim ProcedureName As String
Dim ProcStart As Long, ProcEnd As Long, ProcCodeEnd As Long
Dim p_line As String, lPos As Long, p_type As String
Dim p_code_insert() As String: ReDim p_code_insert(0)
RemoveBenchCode
p_index = 0
For Each VBComp In ThisWorkbook.VBProject.VBComponents
With VBComp.CodeModule
If .Name <> "modBench" Then
i = .CountOfDeclarationLines + 1
While i < .CountOfLines
ProcedureName = .ProcOfLine(i, ProcedureKind)
ProcStart = .ProcBodyLine(ProcedureName, ProcedureKind)
ProcStartOffset = 1
While Right(RTrim(.Lines(ProcStart + ProcStartOffset - 1, 1)), 1) = "_"
ProcStartOffset = ProcStartOffset + 1
Wend
.InsertLines ProcStart + ProcStartOffset, " p_in " & p_index & CLT_1
ProcEnd = i + .ProcCountLines(ProcedureName, ProcedureKind) - 1
ProcCodeEnd = ProcEnd
While Left(LTrim(.Lines(ProcCodeEnd, 1)), 4) <> "End "
ProcCodeEnd = ProcCodeEnd - 1
Wend
For j = ProcStart + ProcStartOffset To ProcCodeEnd - 1
p_line = " " & .Lines(j, 1) & " "
lPos = InStr(p_line, " Exit Function "): p_type = " Exit Function "
If lPos = 0 Then lPos = InStr(p_line, " Exit Sub "): p_type = " Exit Sub "
If lPos = 0 Then lPos = InStr(p_line, " Exit Property "): p_type = " Exit Property "
If lPos > 0 Then
p_line = Mid(p_line, 2, lPos - 1) & "modBench.p_out " & p_index & ": " & Mid(p_line, lPos + 1, Len(p_line)) & CLT_3 & "modBench.p_out " & p_index & ": " & CLT_2
.DeleteLines j, 1
.InsertLines j, p_line
End If
Next
.InsertLines ProcCodeEnd, " p_out " & p_index & CLT_1
ProcCodeEnd = ProcCodeEnd + 1
ProcEnd = ProcEnd + 1
i = ProcEnd + 1
ReDim Preserve p_code_insert(p_index + 2)
p_code_insert(p_index + 2) = " p_names(" & p_index & ") = """ & VBComp.Name & "." & ProcedureName & """"
p_index = p_index + 1
Wend
Else
Set ThisModule = VBComp.CodeModule
End If
End With
Next
p_index = p_index - 1
If p_index < 0 Then Exit Sub
p_code_insert(0) = " p_max_index = " & p_index
p_code_insert(1) = " ReDim p_names(" & p_index & ") As String"
For i = 0 To UBound(p_code_insert)
p_code_insert(i) = p_code_insert(i) & Space(99 - Len(p_code_insert(i))) & CLT_1
Next
With ThisModule
i = .CountOfDeclarationLines + 1
While i < .CountOfLines
If Right(.Lines(i, 1), Len(CLT_4)) = CLT_4 Then
i = i + 1
.InsertLines i, Join(p_code_insert, vbCrLf)
Exit Sub
End If
i = i + 1
Wend
End With
End Sub
Sub RemoveBenchCode()
Dim VBComp As VBIDE.VBComponent, i As Long, p_line As String, p_part As String, cit_pos As Long
For Each VBComp In ThisWorkbook.VBProject.VBComponents
With VBComp.CodeModule
i = 1
While i < .CountOfLines
p_line = .Lines(i, 1)
If Right(p_line, Len(CLT_1)) = CLT_1 Then
.DeleteLines i, 1
i = i - 1
ElseIf Right(p_line, Len(CLT_2)) = CLT_2 Then
p_part = Left(p_line, Len(p_line) - Len(CLT_2))
cit_pos = InStrRev(p_part, """")
If cit_pos > 0 Then
If Right(Left(p_part, cit_pos), Len(CLT_3)) = CLT_3 Then
p_part = Right(p_part, Len(p_part) - cit_pos)
p_line = Left(p_line, Len(p_line) - Len(CLT_2) - Len(CLT_3) - Len(p_part))
p_line = Replace(p_line, p_part, "")
.DeleteLines i, 1
.InsertLines i, p_line
End If
End If
End If
i = i + 1
Wend
End With
Next
End Sub
Sub End_Benchmark()
Dim p_max_index As Long, i As Long, p_names() As String, sOutputFile As String, WBout As Workbook, WSout As Worksheet
Dim fso As Object
Dim SortOrder() As Long, tmpSort As Long, CntUsed As Long
Dim IsSorted As Boolean
p_max_index = 0
ReDim p_names(0) As String
'MODBENCH TO INSERT PROCEDURE INFO START HERE
CntUsed = 0
ReDim SortOrder(0) As Long
For i = 0 To p_max_index
If p_count(i) > 0 Then
ReDim Preserve SortOrder(CntUsed)
SortOrder(CntUsed) = i
CntUsed = CntUsed + 1
End If
Next
IsSorted = False
While Not IsSorted
IsSorted = True
i = 0
While i <= CntUsed - 2
If p_module_time(SortOrder(i)) < p_module_time(SortOrder(i + 1)) Then
IsSorted = False
tmpSort = SortOrder(i)
SortOrder(i) = SortOrder(i + 1)
SortOrder(i + 1) = tmpSort
End If
i = i + 1
Wend
Wend
sOutputFile = ThisWorkbook.Path & "\Benchmark results for " & Left(ThisWorkbook.Name, InStrRev(ThisWorkbook.Name, ".")) & "xlsx"
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists(sOutputFile) Then
Application.DisplayAlerts = False
Set WBout = Application.Workbooks.Open(sOutputFile)
Application.DisplayAlerts = True
Else
Set WBout = Application.Workbooks.Add
WBout.SaveAs sOutputFile
End If
Set WSout = WBout.Worksheets(1)
FormatBlock WSout, CntUsed
WSout.Cells(1, 1).Value = "Benchmark of " & ThisWorkbook.Name
WSout.Cells(1, 6).Value = "D_Out:" & p_call_stack_indx
WSout.Cells(2, 1).Value = Now()
WSout.Cells(3, 3).Value = "Time including subroutines"
WSout.Cells(3, 5).Value = "Time excluding subroutines"
WSout.Cells(4, 1).Value = "Module"
WSout.Cells(4, 2).Value = "No. runs"
WSout.Cells(4, 3).Value = "Total run time"
WSout.Cells(4, 4).Value = "Avg. time/run"
WSout.Cells(4, 5).Value = "Total run time"
WSout.Cells(4, 6).Value = "Avg. time/run"
For i = 0 To CntUsed - 1
WSout.Cells(5 + i, 1).Value = p_names(SortOrder(i))
WSout.Cells(5 + i, 2).Value = p_count(SortOrder(i))
FillWithFormat WSout.Cells(5 + i, 3), p_total_time(SortOrder(i))
FillWithFormat WSout.Cells(5 + i, 4), p_total_time(SortOrder(i)) / p_count(SortOrder(i))
FillWithFormat WSout.Cells(5 + i, 5), p_module_time(SortOrder(i))
FillWithFormat WSout.Cells(5 + i, 6), p_module_time(SortOrder(i)) / p_count(SortOrder(i))
Next
WBout.Save
RemoveBenchCode
'WBout.Close True
End Sub
Public Sub FillWithFormat(rIn As Range, cCounter As Currency)
Dim m_PerfFrequency As Currency, dTime As Double, unit As String, lDigits As Long, lMega As Long
QueryPerformanceFrequency m_PerfFrequency
dTime = cCounter / m_PerfFrequency * 1000000
rIn.Value = dTime
If dTime = 0 Then
rIn.NumberFormat = "0"" s"""
Else
lMega = Int(Log(dTime) / Log(1000))
If lMega < 0 Then lMega = 0
lDigits = 3 * lMega + 2 - Int(Log(dTime) / Log(10))
Select Case lMega
Case 0: unit = "µs"
Case 1: unit = "ms"
Case 2: unit = "s"
Case 3: unit = "ks"
End Select
If lDigits <= 0 Then
rIn.NumberFormat = "0" & String(lMega, ",") & """ " & unit & """"
Else
rIn.NumberFormat = "0." & String(lDigits, "0") & String(lMega, ",") & """ " & unit & """"
End If
End If
End Sub
Public Function TimestringFromCounter(cCounter As Currency) As String
Dim m_PerfFrequency As Currency, dTime As Double, unit As String, lDigits As Long, sFormatString
QueryPerformanceFrequency m_PerfFrequency
dTime = cCounter / m_PerfFrequency
unit = "s"
If dTime < 1 Then dTime = dTime * 1000: unit = "ms"
If dTime < 1 Then dTime = dTime * 1000: unit = "µs"
If dTime <= 0.005 Then
TimestringFromCounter = "<0.01 µs"
Else
lDigits = 2 - Int(Log(dTime) / Log(10))
If lDigits < 0 Then lDigits = 0
sFormatString = "0"
If lDigits > 0 Then sFormatString = "0." & String(lDigits, "0")
TimestringFromCounter = Replace(Format(dTime, sFormatString) & " " & unit, ",", ".")
End If
End Function
Sub FormatBlock(WS As Worksheet, lModuleLines As Long)
WS.Range(WS.Cells(1, 1), WS.Cells(5 + lModuleLines, 1)).EntireRow.Insert Shift:=xlDown
WS.Columns("A:A").ColumnWidth = 50
WS.Columns("B:B").ColumnWidth = 7.86
WS.Columns("C:F").ColumnWidth = 12.86
WS.Range("A1").Font.Size = 14
WS.Range("A2").NumberFormat = "yyyy/mm/dd hh:mm:ss"
WS.Range("A2").HorizontalAlignment = xlLeft
WS.Range("B:F").HorizontalAlignment = xlCenter
WS.Range("C3:D3").Merge
WS.Range("E3:F3").Merge
With WS.Range("A1:F2").Interior
.ThemeColor = xlThemeColorDark1
.TintAndShade = -4.99893185216834E-02
End With
With WS.Range("A3:F4").Interior
.ThemeColor = xlThemeColorAccent6
.TintAndShade = 0.599993896298105
End With
With WS.Range(WS.Cells(5, 1), WS.Cells(4 + lModuleLines, 6)).Interior
.ThemeColor = xlThemeColorAccent6
.TintAndShade = 0.799981688894314
End With
With WS.Range(WS.Cells(3, 3), WS.Cells(4 + lModuleLines, 4))
.Borders(xlEdgeLeft).LineStyle = xlContinuous
.Borders(xlEdgeLeft).Weight = xlThin
.Borders(xlEdgeRight).LineStyle = xlContinuous
.Borders(xlEdgeRight).Weight = xlThin
End With
With WS.Range(WS.Cells(1, 1), WS.Cells(4 + lModuleLines, 6))
.Borders(xlEdgeLeft).LineStyle = xlContinuous
.Borders(xlEdgeLeft).Weight = xlMedium
.Borders(xlEdgeTop).LineStyle = xlContinuous
.Borders(xlEdgeTop).Weight = xlMedium
.Borders(xlEdgeBottom).LineStyle = xlContinuous
.Borders(xlEdgeBottom).Weight = xlMedium
.Borders(xlEdgeRight).LineStyle = xlContinuous
.Borders(xlEdgeRight).Weight = xlMedium
End With
With Range("A2:F2")
.Borders(xlEdgeBottom).LineStyle = xlContinuous
.Borders(xlEdgeBottom).Weight = xlMedium
End With
End Sub
So I have this code that sets object properties of a class in a for loop, saving each object as an element in an array, BREobjects(). The very next code is below and the first BREobjects(i).BREdays is throwing an
Object variable not set error.
It's a Public array so it shouldn't need to be redim'ed or anything. Anyone know what's happening?
Code that sets the object properties:
'creates a new object for each BRE day/time combination
count = 0
For Each i In BREitems
BREdaysString = Split(Cells(i.Row, "c").value, ", ")
For j = LBound(BREdaysString) To UBound(BREdaysString)
count = count + 1
ReDim Preserve BREobjects(count)
Set BREobjects(count) = New BREpptObjects
BREobjects(count).BREname = Cells(i.Row, "a").value
BREobjects(count).BREcategory = Cells(i.Row, "b").value
BREobjects(count).BREstartTime = Cells(i.Row, "d").value
BREobjects(count).BRElength = Cells(i.Row, "e").value
BREobjects(count).BREtimeRight = Right(Cells(i.Row, "d").value, 2)
BREobjects(count).BREdays = BREdaysString(j)
'Sets the start row number accounting for BREs that start on the half hour
If BREobjects(count).BREtimeRight = 0 Then
BREobjects(count).BREstartRow = (Cells(i.Row, "d").value / 100) + 3
BREobjects(count).BREremainder = 0
ElseIf BREobjects(count).BREtimeRight <> 0 Then
BREobjects(count).BREstartRow = ((Cells(i.Row, "d").value - BREobjects(count).BREtimeRight) / 100) + 3
BREobjects(count).BREremainder = 1
End If
'determines the row the BRE ends in
If BREobjects(count).BRElength - Fix(BREobjects(count).BRElength) = 0 Then
BREobjects(count).BREendRow = BREobjects(count).BREstartRow + BREobjects(count).BRElength - 1
ElseIf BREobjects(count).BRElength - Fix(BREobjects(count).BRElength) > 0 Or BREobjects(count).BREremainder = 1 Then
BREobjects(count).BREendRow = BREobjects(count).BREstartRow + Fix(BREobjects(count).BRElength)
End If
If BREobjects(count).BREremainder = 1 And BREobjects(count).BRElength >= 1 Then
BREobjects(count).BREendRow = BREobjects(count).BREendRow + 1
End If
'sets the end time
If BREobjects(count).BRElength - Fix(BREobjects(count).BRElength) = 0 Then
BREobjects(count).BREendTime = BREobjects(count).BREstartTime + (100 * BREobjects(count).BRElength)
ElseIf BREobjects(count).BRElength - Fix(BREobjects(count).BRElength) > 0 Then
BREtimeRight = Right(BREobjects(count).BRElength, 2)
BREobjects(count).BREendTime = BREobjects(count).BREstartTime + (100 * Fix(BREobjects(count).BRElength)) + (BREtimeRight * 60)
End If
BREobjects(count).BREID = BREobjects(count).BREname & " " & BREobjects(count).BREdays & " " & _
BREobjects(count).BREstartTime & " " & BREobjects(count).BREendTime & " " & BREobjects(count).BRElength
Next j
Erase BREdaysString
Next i
'This loop throws an Object variable or with block variable not set error.
'Thrown on the array in the line BREdays = BREobjects(i).BREdays.
Back:
For i = LBound(BREobjects) To UBound(BREobjects)
Dim BREdays As String
BREdays = BREobjects(i).BREdays
If FiveDay = True And BREdays = "Saturday" Or BREdays = "Sunday" Then
Call DeleteElement(i, BREobjects()) 'Deletes the BREppt Object from the BREobjects array
ReDim Preserve BREobjects(UBound(BREobjects) - 1) 'Shrinks the array by one, removing the last one
GoTo Back 'Restarts the loop because the UBound has changed
End If
Debug.Print BREobjects(i).BREID
Next i
If you were to refactor you code using a collection and move some of the property setting to the class module it could reduce the code to something like this.
Sub ExportToPPTButton_Click()
Dim wb As Workbook, ws As Worksheet, iLastRow As Long
Set wb = ThisWorkbook
Set ws = wb.Sheets("Sheet1")
iLastRow = ws.Cells(Rows.count, 1).End(xlUp).Row
Dim BREobjects As New Collection
Dim obj As BREpptObjects2, arDays As Variant
Dim i As Long, dow As Variant, sKey As String, s As String
Dim FiveDays As Boolean
' dictionary to count multiple day/time
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")
FiveDays = True
For i = 5 To iLastRow
s = ws.Cells(i, "D")
s = Replace(s, " ", "") 'remove spaces
arDays = Split(s, ",")
For Each dow In arDays
s = LCase(Left(dow, 3))
If (FiveDays = True) And (s = "sat" Or s = "sun") Then
' skip weekends
Else
Set obj = New BREpptObjects2
obj.BREDays = dow
obj.initialise ws.Cells(i, 1)
' avoid duplicate day/time
sKey = obj.BREDays & obj.BREstartTime
obj.BREpic = dict(sKey) + 0
dict(sKey) = dict(sKey) + 1
' add to collection
BREobjects.Add obj, obj.BREID
End If
Next
Next
' set total objects in cell
For Each obj In BREobjects
sKey = obj.BREDays & obj.BREstartTime
obj.BREobjInCell = dict(sKey)
Next
MsgBox BREobjects.count & " objects added to collection"
For Each obj In BREobjects
obj.dump ' debug.print objects
Next
End Sub
Note : I used Public here for demo but use Private in your code
' class BREpptObjects2
Public BREname As String, BRElocation As String, BREcategory As String
Public BREstartTime As String, BREendTime As String
Public BRElength As Double
Public BREDays As String, BREID As String, BREStartRow, BREEndRow
Public BREobjInCell As Integer, BREpic As Integer
Sub initialise(rng As Range)
Dim StartHour As Integer, StartMin As Integer
Dim DurHour As Integer, DurMin As Integer
Dim EndHour As Integer, EndMin As Integer
With rng
BREname = .Offset(0, 0).Value ' A
BRElocation = .Offset(0, 1).Value 'B
BREcategory = .Offset(0, 2).Value 'C
BREstartTime = .Offset(0, 4).Value 'E
BRElength = .Offset(0, 5).Value 'F
End With
StartHour = Int(BREstartTime / 100)
StartMin = BREstartTime Mod 100
DurHour = Fix(BRElength)
DurMin = (BRElength - DurHour) * 60
' set end time
EndHour = StartHour + DurHour
EndMin = StartMin + DurMin
If EndMin > 60 Then
EndMin = EndMin - 60
EndHour = EndHour + 1
End If
BREendTime = EndHour * 100 + EndMin
'Sets the start row number accounting for BREs that start on the half hou
BREStartRow = StartHour + 3
BREEndRow = EndHour + 3
BREID = BREname & " " & BREDays & " " & _
BREstartTime & " " & BREendTime & " " & BRElength
End Sub
Sub dump()
Debug.Print "ID [" & BREID & "]"
Debug.Print "StartTime", BREstartTime, "End TIme", BREendTime, "Length", BRElength
Debug.Print "StartRow", BREStartRow, "EndRow", BREEndRow
Debug.Print "pic", BREpic, "objInCell", BREobjInCell
End Sub
I have an excel sheet with strings in the rows.
I have a txt file.
I already have the specific number of lines I want to insert the strings.
but when I use "write" it deletes all and then inserts the string.
How can I insert a string into a specific line in a text file? i'll use a loop to open and close all the txt files.
the code works. just need to put the string in the txt file.
p.s the note is in Hebrew.
Sub SearchTextFile()
'--------------------------------------------------------------------------------------------------úçéìú øéöú ÷åã
Dim Start, Finish, TotalTime As Date
Start = Timer
'--------------------------------------------------------------------------------------------------áéèåì çéùåáéí åòãëåðé îñê åäúøàåú
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.AskToUpdateLinks = False
'--------------------------------------------------------------------------------------------------äçæøú çéùåáéí åòãëåðé îñê åäúøàåú
'Application.Calculation = xlCalculationAutomatic
'Application.ScreenUpdating = True
'Application.DisplayAlerts = True
'Application.AskToUpdateLinks = True
Dim strLine1, strLine2, strSearch1, strSearch2, Mid1, Mid2 As String
Dim i, j, z, h As Integer
Dim x, LineCount1, LineCount2 As Long
Dim blnFound As Boolean
x = 2
LineCount1 = 0
h = 0
Do Until IsEmpty(Cells(x, 2))
myFileCOMPANY = "L:\" & Cells(x, 2) & "\COMPANY.bat" 'áãé÷ä øàùåðéí äàí îñôø äçáøä ÷ééí áëìì
If Not Dir(myFileCOMPANY) = "" Then 'àí ìà øé÷
strFileName = "L:\" & Cells(x, 2) & "\COMPANY.bat" 'ðúéá - àéôä ìçôù
strSearch1 = Cells(x, 7) 'îä ìçôù
strSearch1 = "If Exist Dfile" & Format(strSearch1, "000") 'ùéðåé ôåøîè
i = FreeFile
On Error Resume Next
Open strFileName For Input As #i
Do While Not EOF(i)
LineCount1 = LineCount1 + 1
Line Input #i, strLine1
If InStr(1, strLine1, strSearch1, vbBinaryCompare) > 0 Then 'äáéã÷ä òöîä äàí äè÷ñè ùîçôùéí ÷ééí áùåøä äæå
strSearch2 = "pz-"
Line Input #i, strLine2
For j = 1 To 4
If InStr(1, strLine2, strSearch2, vbBinaryCompare) + 1 > 0 Then 'äáéã÷ä òöîä äàí äè÷ñè ùîçôùéí ÷ééí áùåøä äæå
Cells(x, 11) = Cells(x, 2) 'îñôø çáøä
Cells(x, 12) = Format(Cells(x, 7), "000") 'îñôø úú
Cells(x, 13) = LineCount1 + j 'îñôø ùåøä
blnFound = True
Cells(x, 14) = Len(strLine2) 'àåøê ùåøä
Cells(x, 15) = "1." & strSearch1 & " 2." & strSearch2 'úå ùàåúå çéôùå
Cells(x, 16) = strLine2 'è÷ñè áùåøä ìôðé
Mid1 = Mid(Cells(x, 16), Cells(x, 14) - 12, 5)
Cells(x, 17) = Cells(x, 16) & " " & Mid1 & Cells(x, 3) & ".pdf"
For z = 1 To 10 'áîéãä åéù òåã îàåúä äçáøä åàåúå äúú àæ ëàï äúåñôåú ëøèéñéí ðöáøéí
If Cells(x, 7) = Cells(x + z, 7) And Cells(x, 2) = Cells(x + z, 2) Then
Cells(x + z, 16) = Cells(x + h, 17)
Mid2 = Mid(Cells(x + z, 16), Cells(x, 14) - 12, 5)
Cells(x + z, 17) = Cells(x + z, 16) & " " & Mid2 & Cells(x + z, 3) & ".pdf"
h = h + 1
End If
Next z
Exit For
End If
Next j
Open myFileCOMPANY For Output As #i
Write #i, "dfgdfg" 'Cells(x + z, 17)
Exit Do
Else: Cells(x, 11) = Cells(x, 2)
Cells(x, 12) = Cells(x, 7)
Cells(x, 15) = "Dfile" & Format(Cells(x, 7), "000") & " not found"
End If
Loop
Close #i
LineCount1 = 0
Else: Cells(x, 11) = "No folder number " & Cells(x, 2)
End If
x = x + h
h = 0
x = x + 1
Loop
'--------------------------------------------------------------------------------------------------äçæøú çéùåáéí åòãëåðé îñê åäúøàåú
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.AskToUpdateLinks = True
'--------------------------------------------------------------------------------------------------æîï ñéåí øéöú ÷åã åçéùåá
Finish = Timer
TotalTime = Format((Finish - Start) / 86400, "hh:mm:ss")
MsgBox ("äãå''ç îåëï" & vbNewLine & "æîï øéöú ÷åã: " & TotalTime)
End Sub
Not sure what code you have tried. It would be easier if you included your code.
You could try using:
If Application.Options.Overtype Then
Application.Options.Overtype = False
End If
If you are trying to add a line to the end of your document you can use the following code:
Function WordAddEnd()
Dim objWord As Object, objDoc As Object, objSelection As Object
Dim endpoint As Integer, moveit As Integer
Dim FileString As String
endpoint = 6
moveit = 0
FileString = "C:\location\folder\document.docx"
Set objWord = CreateObject("Word.Application")
Onerror resumenext
'change error handling
Set objDoc = objWord.documents.Open(FileString)
Set objSelection = objWord.Selection
With objSelection
.EndKey endpoint, moveit
'finds end point of document
.typeparagraph
'goes to next line (like pressing the enter key)
.TypeText ("It's some text you wanted")
'your text here
End With
objWord.documents.Close
End Function
If the document in question is already open, there will be an error so you'll need some error handling in here.
Compiler Error: End With Has No With. I know that this is wrong, and there is something in my code in where I am not calling it correctly that is making it mess up but I cannot find it. I'm just trying to grab information off of my sheet1 so that I can use it later on.
With ThisWorkbook.Sheets("Sheet1")
While (Counter <= 300)
Pcounter = .Cells(ACBoxCounter, 2)
If (Pcounter <> "") Then
ACounter = ACounter + 1
End If
ACBCounter = ACBCounter + 30
Wend
While (OverallACounter < ACounter)
Set objStream = CreateObject("ADODB.Stream")
objStream.Charset = "iso-8859-1"
objStream.Open
ExampleString = .Cells(Row2Counter + 22, 3)
ChooseM = Split(ExampleString, "-")(1)
If (ChooseM = "8")
M = "II"
P = 97
Label = .Cells(Row2Counter, 2)
ElseIf (ChooseM = "13") Then
Model = "A II"
P = 10
Label = "A6_" & .Cells(Row2Counter, 2)
ElseIf (ChooseM = "19") Then
M = "AC1I"
P = 56
Label = "A9_" & .Cells(Row2Counter, 2)
End If
OverallD = 0
Overall= 0
OverallB = 0
ChooseBoxType = Split(ExampleString, "-")(2)
If ((StrComp(ChooseB, "1") = 0) Or (StrComp(ChooseB, "1M") = 0)) Then
BoxInputT= "1 Phase"
ElseIf ((StrComp(ChooseB, "2") = 0) Or (StrComp(ChooseB, "2M") = 0)) Then
BoxInput= "2"
ElseIf ((StrComp(ChooseB ,"3") = 0) Or (StrComp(ChooseBo, "3M") = 0)) Then
BoxInput= "3"
End If
objStream.WriteText (" <" & .Cells(Row2Counter, 2).Text & ">" & vbLf)
Wend
End With
Compiler Error: End With Has No With
I had a working query but it was grabbing all users in AD and I am attempting to narrow this down to the last 90 days. The problem is that I no longer have any outputs even though the query does run. I know that my math is wrong and does not take off 90 days. Can anyone offer assistance with this?
Dim currentDate
currentDate = DateDiff("s", CDate("1/1/1970"), Now()) * 1000#
currentDate = currentDate - 7776000000# 'Subtracts 90 days
'Does the query
objCommand.CommandText = _
"<LDAP://" & strDN & ">;" & _
"(&(objectclass=user)(objectcategory=person)(lastLogonTimestamp<=" & currentDate & "));" & _
"adspath,distinguishedname,sAMAccountName,lastLogonTimestamp,DisplayName,WhenCreated,userAccountControl;subtree"
'Output the query info
Set objRecordSet = objCommand.Execute
rngOut.CurrentRegion.Offset(2).ClearContents
While Not objRecordSet.EOF
rngOut.value = objRecordSet.Fields("DisplayName").value
Set rngOut = rngOut.Offset(0, 1)
rngOut.value = objRecordSet.Fields("sAMAccountName").value
Set rngOut = rngOut.Offset(0, 1)
rngOut.value = objRecordSet.Fields("WhenCreated").value
Set rngOut = rngOut.Offset(0, 1)
On Error Resume Next
Set objDate = objRecordSet.Fields("lastLogonTimestamp").value
If (Err.Number <> 0) Then
On Error GoTo 0
dtmDate = ""
Else
On Error GoTo 0
lngHigh = objDate.HighPart
lngLow = objDate.LowPart
If (lngLow < 0) Then
lngHigh = lngHigh + 1
End If
If (lngHigh = 0) And (lngLow = 0) Then
dtmDate = ""
Else
dtmDate = #1/1/1601# + (((lngHigh * (2 ^ 32)) _
+ lngLow) / 600000000) / 1440
End If
End If
rngOut.value = dtmDate
Set rngOut = rngOut.Offset(0, 1)
rngOut.value = objRecordSet.Fields("distinguishedName").value
Set rngOut = rngOut.Offset(0, 1)
Set Uservar = objRecordSet.Fields("userAccountControl")
If Uservar And 2 Then
rngOut.value = "Disabled"
rngOut.Font.ColorIndex = 3
Else
rngOut.value = "Enabled"
rngOut.Font.ColorIndex = 0
End If
Set rngOut = rngOut.Offset(1, -5)
objRecordSet.MoveNext
Wend
I have this working but only when I change (lastLogonTimestamp<=" & currentDate & ")); to (lastLogon<=" & currentDate & ")); and for what I am wanting this does not display the correct user base. Can anyone tell me why?
As documented in the VBScript tag wiki VBScript doesn't expand variables inside strings, so you need to change this:
objCommand.CommandText = _
"<LDAP://" & strDN & ">;" & _
"(&(objectclass=user)(objectcategory=person)(lastLogonTimestamp>=currentDate));" & _
"adspath,distinguishedname,sAMAccountName,lastLogon,DisplayName,WhenCreated,userAccountControl;subtree"
into this:
objCommand.CommandText = _
"<LDAP://" & strDN & ">;" & _
"(&(objectclass=user)(objectcategory=person)(lastLogonTimestamp>=" & currentDate & "));" & _
"adspath,distinguishedname,sAMAccountName,lastLogon,DisplayName,WhenCreated,userAccountControl;subtree"
Also, I'd recommend calculating currentDate as a normal Date value, e.g. like this:
maxAge = 30 'days
currentDate = Now - maxAge
or like this:
maxAge = 30 'days
currentDate = DateAdd("d", -maxAge, Now)
and then convert it to an integer8 value using this code from Richard L. Mueller:
Function DateToInt8(d)
biasKey = CreateObject("Wscript.Shell").RegRead("HKLM\System" & _
"\CurrentControlSet\Control\TimeZoneInformation\ActiveTimeBias")
If (UCase(TypeName(biasKey)) = "LONG") Then
bias = biasKey
ElseIf (UCase(TypeName(biasKey)) = "VARIANT()") Then
bias = 0
For k = 0 To UBound(biasKey)
bias = bias + (biasKey(k) * 256^k)
Next
End If
DateToInt8 = CStr(DateDiff("s", #1/1/1601#, DateAdd("n", bias, d))) & "0000000"
End Function
...
objCommand.CommandText = "<LDAP://" & strDN & ">;" & _
"(&(objectclass=user)(objectcategory=person)(lastLogonTimestamp>=" & _
DateToInt8(currentDate) & "));adspath,distinguishedname,sAMAccountName," & _
"lastLogon,DisplayName,WhenCreated,userAccountControl;subtree"