excel vba getelementsbyid can't get it to work - excel

I am new to objects and I have all of this working except the htm.getelementsbyid. When I get to the rows.length I get the error:
run-time error 91, with object variable not set
Sub get_correct_address()
Dim x As Long, y As Long
Dim htm As Object
Set htm = CreateObject("htmlFile")
row = 6
StrNumCol = 4
StrNamCol = 5
StrTypCol = 6
CityCol = 7
ZipCol = 3
StateCol = 8
With CreateObject("msxml2.xmlhttp")
.Open "GET", "http://production.shippingapis.com/ShippingAPITest.dll?API=Verify&XML= <AddressValidateRequest%20USERID=""968APPRA1046"">" & _
"<Address>" & _
"<Address1></Address1>" & _
"<Address2>" & CStr(Sheets("import").Cells(row, StrNumCol).value) + " " + Sheets("import").Cells(row, StrNamCol).value + " " + Sheets("import").Cells(row, StrTypCol).value & "</Address2>" & _
"<City>" & CStr(Sheets("import").Cells(row, CityCol).value) & "</City>" & _
"<State>" & CStr(Sheets("import").Cells(row, StateCol).value) & "</State>" & _
"<Zip5></Zip5>" & _
"<Zip4>" & CStr(Sheets("import").Cells(row, ZipCol).value) & "</Zip4>" & _
"</Address>" & _
"</AddressValidateRequest>" & _
""", False"
.send
htm.body.innerhtml = .responsetext
End With
With htm.getelementbyid("comps-results")
For x = 0 To .Rows.length - 1
For y = 0 To .Rows(x).Cells.length - 1
Sheets(1).Cells(x + 1, y + 1).value = .Rows(x).Cells(y).innertext
Next y
Next x
End With
'http://production.shippingapis.com/ShippingAPITest.dll?API=Verify&XML=<AddressValidateRequest%20USERID="xxxxxxxxxxxx">
End Sub

I cannot seem to open the object at the address in your code (it must be protected). That said, the most likely problem is that htm.getelementbyid("comps-results") is returning nothing. Verify the values and try stepping through your code with F8 and verify that .Rows.Length has a value. If it does not, the problem may lie in the element ("comps-result") you are referencing. Also verify that .Rows.Length is what you want. Perhaps you want Rows.Count?
With htm.getelementbyid("comps-results")
For x = 0 To .Rows.Count - 1
For y = 0 To .Rows(x).Cells.Count - 1
Sheets(1).Cells(x + 1, y + 1).Value = .Rows(x).Cells(y).innertext
Next y
Next x
End With

Related

Getting a method or data member not found in a class module

Here is the code for the class module (where it errors on the code module):
Private Sub CommandButton_Click()
Dim VBAEditor As VBIDE.VBE
Dim VBProj As VBIDE.VBProject
Dim VBComp As VBIDE.VBComponent
Dim CodeMod As VBIDE.CodeModule
Dim mdl As Object
Dim mdl_exits As Boolean
Dim mdl_name As String
Dim macro_name As String
Dim macro_exists As Boolean
mdl_name = "SaveButtons"
For Each mdl In ThisWorkbook.VBProject.VBComponents
If mdl.Name = mdl_name And mdl.Type = 1 Then
Set prrf_Module = mdl
mdl_exists = True
Exit For
End If
Next
If mdl_exists Then GoTo it_exists
Set prrf_Module = ThisWorkbook.VBProject.VBComponents.Add(1)
prrf_Module.Name = mdl_name
it_exists:
macro_exists = False
macro_name = SaveButton.Value
new_name:
If macro_exists = True Then
If macro_name = SaveButton.Value Then
macro_name = SaveButton.Value & "1"
Else
macro_name = Left(macro_name, Len(macro_name) - 1) & CInt(Mid(macro_name, Len(macro_name) - 1)) + 1
End If
End If
macro_exists = False
zy = "Userform1.show"
strMacro = "Sub " & "CommandButton1" & vbCr
strMacro = strMacro & " " & zy & vbCr
strMacro = strMacro & "End Sub" & vbCr
Debug.Print "strMacro is " & vbCr & strMacro
'Set prrf_Module = ThisWorkbook.VBProject.VBComponents.Add(1)
Dim d, e, f, y
For y = 1 To 2
With btn_Gen.CodeModule
d = .CountOfLines
.insertlines 1, "Sub CommandButton" & y & "_Click()"
For e = LBound(t) To UBound(t)
countlines = countlines + 1
upper = UBound(t)
xy = countlines + 1
.insertlines xy, " " & t(e)
Next e
.insertlines xy + 1, "End Sub"
End With
Next y
End Sub
And here is my module code (that runs till I click commandbutton1)
Sub showuserform1()
Dim x, y
Dim z() As String
Set btn_nm = New Scripting.Dictionary
Set lbl_tx = New Scripting.Dictionary
Set code = New Scripting.Dictionary
repeatx:
x = UCase(InputBox("(H)orizontal or (V)ertical?", "Orientation", "H"))
If x = "H" Then
orientation = "Horizontal"
ElseIf x = "V" Then
orientation = "Vertical"
Else
MsgBox ("Input either 'H' or 'V'")
GoTo repeatx
End If
repeatcount:
count = InputBox("How many buttons do you want? ", "Button Count", "1")
If count < 1 Then
MsgBox ("Input Quantity of Buttons, enter at least 1")
GoTo repeatcount:
End If
For y = 1 To count
btn_nm(y) = InputBox("What do you want CommandButton" & y + 1 & " to say?", "CommandButton name", "CommandButton" & y)
lbl_tx(y) = InputBox("What do you want Label" & y + 1 & " to say?", "Label text", "Label" & y)
btn_Gen_uf2.Label1.Caption = "Enter Code in Window - max 8k characters"
btn_Gen_uf2.TextBox1.Value = ""
repeatshow:
btn_Gen_uf2.TextBox1.SetFocus
btn_Gen_uf2.Show
If btn_Gen_uf2.TextBox1.Value = "" Then
MsgBox "Enter Code in Window before selecting OK"
GoTo repeatshow:
End If
t = Split(btn_Gen_uf2.TextBox1.Text, vbCrLf)
ReDim z(0 To UBound(t), 1 To count)
For w = LBound(t) To UBound(t)
MsgBox t(w)
'Debug.Print "z(" & w & "," & y & ") = " & t(w)
z(w, y) = t(w)
Next w
Next y
' Do this last
btn_Gen.Show
End Sub
This is crossposted from excelforum.
I added the declarations (see above) and now am getting an error on this line: Dim VBAEditor as VBIDE.VBE
The error is "User-defined type not defined". Am I missing a reference?
With rory's help, I made this one change and most of the code is working.
With Prrf_Module.CodeModule
instead of
With btn_Gen.Codemodule

Check values in column(s) if all are the same

Currently I'm creating a check for a column.
Goal: I have a column called currency which I need to check if they are all the same for each Bank (Column A). If there are other currency then it will prompt me.
Additional goal: I would also like to include in the checking the one in column E (Currency (Bank Charge)) to make sure that all currencies for that bank are the same.
Problem: I already have a working code using scripting.dictionary, however, I have some trouble clearing the dictionary for the first loop / currencies for the first Bank. I tried to clear the dictionary before it proceeds to another bank. But it is not working.
Below is the screenshot of what I would like to check:
Below is the current code that I have:
Sub CurrencyTestCheck()
Dim wksSource As Worksheet: Set wksSource = ThisWorkbook.Sheets("Test1")
Dim i As Long
Dim x As Long
Dim lastRow As Long
Dim strBankName As String
Set d = CreateObject("Scripting.dictionary")
Application.ScreenUpdating = False
lastRow = wksSource.Cells(wksSource.Rows.Count, "C").End(xlUp).Row
For i = 2 To lastRow
If Len(wksSource.Cells(i, 1).Value) > 0 Then 'If a new bank starts
If Len(strBankName) > 0 Then
For Each k In d.Keys
strCheck = k
countCurrency = d(k)
msg = msg & strCheck & " - " & countCurrency & vbNewLine
x = x + 1
Next k
If x > 1 Then
MsgBox "There are different currencies for bank " & strBankName & vbNewLine & _
vbNewLine & msg, vbCritical, "Warning"
Else
MsgBox "Currencies are all the same for " & strBankName, vbInformation, "Same currencies"
End If
d.RemoveAll
End If
strBankName = wksSource.Cells(i, 1).Value
End If
'Currency for each Bank
tmp = Trim(wksSource.Cells(i, 3).Value)
If Len(tmp) > 0 Then d(tmp) = d(tmp) + 1
Next i
If Len(strBankName) > 0 Then
For Each k In d.Keys
strCheck = k
countCurrency = d(k)
msg = msg & strCheck & " - " & countCurrency & vbNewLine
x = x + 1
Next k
If x > 1 Then
MsgBox "There are different currencies for bank " & strBankName & vbNewLine & _
vbNewLine & msg, vbCritical, "Warning"
Else
MsgBox "Currencies are all the same for " & strBankName, vbInformation, "Same currencies"
End If
End If
Application.ScreenUpdating = True
End Sub
Output:
Previous values are still in the dictionary (USD - 3 and AUD - 2)
Appreciate if you also have another suggestion to do the checking.
You might have forgotten to reset your currency discrepancy counter x.
Set it to x = 0 after the first bank's loop.
i.e.
...
...
'Currency for each Bank
tmp = Trim(wksSource.Cells(i, 3).Value)
If Len(tmp) > 0 Then d(tmp) = d(tmp) + 1
Next i
' Add these two lines:
x = 0
msg = ""
If Len(strBankName) > 0 Then
For Each k In d.Keys
strCheck = k
...
...
And like TinMan said, also reset the msg so the previous bank's results don't leak into your the next bank.

Memory problem with macro in Excel: How do I solve this problem?

I have a problem with a macro in Excel. Here the code. There are actually quite a few subs that are I am not reporting for a matter of space. However, the most important one is attached.
Sub randomdata_generator()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Dim FromProducts As Integer
Dim ToProducts As Integer
Dim StepProducts As Integer
Dim FromStations As Integer
Dim ToStations As Integer
Dim StepStations As Integer
FromProducts = Range("G1").Value
ToProducts = Range("I1").Value
StepProducts = Range("K1").Value
FromStations = Range("G2").Value
ToStations = Range("I2").Value
StepStations = Range("K2").Value
For h1 = FromProducts To ToProducts Step StepProducts
For h2 = FromStations To ToStations Step StepStations
Index = 0
For xx1 = 1 To 17 Step 1 'NC
x1 = h1
x2 = h2
Range("B1").Value = x1
D = Application.WorksheetFunction.Round(x1 * 0.1, 0)
E = Application.WorksheetFunction.Round(x1 * 0.2, 0)
BAEG = Application.WorksheetFunction.Round(x1 * 0.35, 0)
For xx2 = 1 To 5 Step 1
If x2 >= x1 Then GoTo prossimo
Range("B2").Value = x2
Range("B4").Value = 20 * x2 'D
For x3 = 1 To 5 'NI
Range("B3").Value = x3
If x3 > 1 Then
q = 3
Else
q = 1
End If
For g = 1 To q
x5 = 1
Range("B5").Value = x5
s = E
For i = 0 To s - 1
Range("A25").Offset(0, D + i).Value = 0.3
Range("A28").Offset(0, D + i).Value = 0.2
Range("A46").Offset(0, D + i).Value = 0.009
Next
Next
Next
Next
Next
Next
Next
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
This is the part of the code that saves the new file that has been generated.
Sub salvanuovo()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Dim wbkCurrent As Workbook
Index = Index + 1
If Index Mod 200 = 0 Then
newHour = Hour(Now())
newMinute = Minute(Now()) + 1
newSecond = Second(Now()) + 30
waitTime = TimeSerial(newHour, newMinute, newSecond)
Application.Wait waitTime
DoEvents
End If
ActiveWorkbook.SaveCopyAs Filename:=ThisWorkbook.Path & "\Data\Dati(" & (x1 / 10) & "_" & (x2) & "_" & Index & ").xlsm" 'example: "C:\Users\lucag\Desktop\randomdata_generator_alternativa\Dati(" & Index & ").xlsm"
Workbooks.Open Filename:=ThisWorkbook.Path & "\Data\Dati(" & (x1 / 10) & "_" & (x2) & "_" & Index & ").xlsm"
Workbooks("Dati(" & (x1 / 10) & "_" & (x2) & "_" & Index & ").xlsm").Activate
Sheets("Foglio1").Select
ActiveWorkbook.SaveAs Filename:=ThisWorkbook.Path & "\Data\Dati(" & (x1 / 10) & "_" & (x2) & "_" & Index & ").xlsx", _
FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
Workbooks("Dati(" & (x1 / 10) & "_" & (x2) & "_" & Index & ").xlsx").Close
Kill (ThisWorkbook.Path & "\Data\Dati(" & (x1 / 10) & "_" & (x2) & "_" & Index & ").xlsm")
Set wbkCurrent = ActiveWorkbook
wbkCurrent.Activate
Set wbkCurrent = Nothing
End Sub
The following image shows the issue. The memory keeps loading until Excel crashes. Any hint on how to solve this problem.
enter image description here
There is no .Copy nor .Paste just some .Value assigned
Selection.ClearContents
Range("A12").Select
This is not a comprehensive answer, just somewhat of a start.
First, Excel VBA treats Integer types as Long internally. This answer shows more on that. So I would recommend using Long unless specific to backward compatibility for older Excel versions.
Next I see you are using worksheet functions. You don't need
D = Application.WorksheetFunction.Round(x1 * 0.1, 0)
as it can be reduced to
D = Round(x1 * 0.1, 0)
On top of that, you are accessing the worksheet an insane amount of times through the nested loops. It would be better, in my opinion, to limit the amount of times VBA must interact with ranges or worksheets to the minimum number of times, such as storing values into an array and dump the full array to the cells.
Additionally, you can look at this answer regarding memory problems as there are quite a few tips that may be applicable here.
And as a total side note, I would recommend using more meaningful variable names, especially when presenting to SO to help people determine what is going on.
The problem was related to the version of Excel. As soon as I move to a 64-bit version of Office 365 rather than the 32-bit version that I had before, everything was solved.

VBA excel - excel creating empty csv files when using application.ontime

I got a macro that runs every 30 seconds using Application.Ontime. Every iteration creates a new csv file containing 8 columns and between 50 to 100 rows. The Application.Ontime normally runs from 8am to 5pm.
The problem is that sometimes during the day the macro just stop storing data in the csv files but still creates csv files. Hence, it still creates csv files but without any data in it.
EDIT:
The files that are created contain headers (StdTenorArray(0))
The variable StdXXXXXX is defined in another macro (button) and is a global variable
Here is the code:
Sub RunOnTime()
Application.CutCopyMode = False
Set ThisWkb = ThisWorkbook
dTime = Now + TimeSerial(0, 0, 30)
Application.OnTime dTime, "RunOnTime"
Call csvFileArray
Set ThisWkb = Nothing
End Sub
The above code calls this macro:
Sub csvFileArray()
Dim StdTenorArray(), ArkArr(5) As Variant
Dim FileName As String
Dim StdTenorCnt, h, j As Long
Set ThisWkb = ThisWorkbook
Application.CutCopyMode = False
ArkArr(1) = "XXXXXXctb"
ArkArr(2) = "XXXXXctb"
ArkArr(3) = "XXXXctb"
ArkArr(4) = "XXXctb"
ArkArr(5) = "XXctb"
ReDim StdTenorArray(ThisWkb.Sheets(ArkArr(1)).Range("B" & Rows.Count).End(xlUp).Row + ThisWkb.Sheets(ArkArr(2)).Range("B" & Rows.Count).End(xlUp).Row + ThisWkb.Sheets(ArkArr(3)).Range("B" & Rows.Count).End(xlUp).Row + ThisWkb.Sheets(ArkArr(4)).Range("B" & Rows.Count).End(xlUp).Row + ThisWkb.Sheets(ArkArr(5)).Range("B" & Rows.Count).End(xlUp).Row)
'Standard tenors
StdTenorCnt = 1
If StdXXXXXX = True Then
For j = 5 To 29
If UCase(ThisWkb.Sheets(ArkArr(1)).Cells(j, 4)) = True _
And WorksheetFunction.IsNumber(ThisWkb.Sheets(ArkArr(1)).Cells(j, 10)) = True _
And WorksheetFunction.IsNumber(ThisWkb.Sheets(ArkArr(1)).Cells(j, 11)) = True _
And IsDate(ThisWkb.Sheets(ArkArr(1)).Cells(j, 7)) = True _
And IsDate(ThisWkb.Sheets(ArkArr(1)).Cells(j, 8)) = True Then
StdTenorArray(StdTenorCnt) = "" & ThisWkb.Sheets(ArkArr(1)).Cells(j, 5) & ";" & Format(ThisWkb.Sheets(ArkArr(1)).Cells(j, 7), "yyyymmdd") & ";" & Format(ThisWkb.Sheets(ArkArr(1)).Cells(j, 8), "yyyymmdd") & ";" & ThisWkb.Sheets(ArkArr(1)).Cells(j, 9) & ";" & Replace(Format(ThisWkb.Sheets(ArkArr(1)).Cells(j, 10), "##0.00"), ",", ".") & ";" & Replace(Format(ThisWkb.Sheets(ArkArr(1)).Cells(j, 11), "##0.00"), ",", ".") & ";" & ThisWkb.Sheets(ArkArr(1)).Cells(j, 6) & ";JPD"
StdTenorCnt = StdTenorCnt + 1
End If
Next j
End I.
.
.
'more storing in the array like the part above
.
.
StdTenorArray(0) = "Symbol;SpotDate;ValueDate;Removed;Bid;Offer;Tenor;Channel"
Set fs = CreateObject("Scripting.FileSystemObject")
'test
app_path = ThisWkb.Path
Set a = fs.CreateTextFile("" & app_path & "\Test\" & Strings.Format(Now(), "dd.mm.yyyy") & " " & Strings.Format(Now(), "hh.mm.ss") & "." & Strings.Right(Strings.Format(Timer(), "#0.00"), 2) & ".csv", True)
For j = 0 To StdTenorCnt - 1
a.WriteLine ("" & StdTenorArray(j) & "")
Next j
a.Close
ThisWkb.Sheets("DKK").Cells(1, 27) = "" & Strings.Format(Now(), "hh:mm:ss") & ":" & Strings.Right(Strings.Format(Timer(), "#0.00"), 2) & ""
ReDim StdTenorArray(0)
Set fs = Nothing
Set a = Nothing
Set ThisWkb = Nothing
Application.CutCopyMode = False
End Sub
Hope someone have a solution to this problem or maybe can point me in the right direction.
Have a nice weekend.
\Kristian

Replace contents across non-contiguous cells across multiple worksheets - Error 1004

I am an Excel VBA novice and am hoping for help on a bit of code. We have a workbook with four identical worksheets, one for each quarter of the year. What I would like to do is run code on a command button click that replaces identifying name information with generic, sequentially numbered information (ex: Joe Smith becomes Male1). There are multiple participant types, represented across the worksheet columns and also in multiple rows within the spreadsheet. So, data for males are in cells C11, C28, C45..C215, J11, J28, J45, X11, X28, X45...AE215 across 4 tabs.
I have a Worksheets Array that identifies the four quarterly tabs, and code for each participant type that defines the range of cells where their names would be listed.
The below code is giving me Error 1004 Method 'Range' of object '_Worksheet' failed at the For Each MaleCare line... Any insight into what I am doing wrong?
Sub DelConfSAVE()
Dim sh As Worksheet
For Each sh In Worksheets(Array("Oct-Dec Attendance", "Jan-Mar Attendance", _
"Apr-Jun Attendance", "Jul-Sep Attendance"))
'Replace Male Caregiver (X)
Dim MaleCare As Range
Dim X As Integer
X = 0
For Each MaleCare In sh.Range("C11, C28, C45, C62, C79, C96, C113, C130, C147, C164, C181, C198, C215, J11, J28, J45, J62, J79, J96, J113, J130,J147, J164, J181, J198, J215, Q11, Q28, Q45, Q62, Q79, Q96, Q113, Q130, Q147, Q164, Q181, Q198, Q215, X11, X28, X45, X62, X79, X96, X113, X130, X147, X164, X181, X198, X215, AE11, AE28, AE45, AE62, AE79, AE96, AE113, AE130, AE147, AE164, AE181, AE198, AE215")
If MaleCare.Value <> "" Then
X = X + 1
MaleCare.Value = "MaleCare" & X
End If
Next MaleCare
Exit For
'Replace Female Caregiver (Y)
Dim FemCare As Range
Dim Y As Integer
Y = 0
For Each FemCare In sh.Range("D11, D28, D45, D62, D79, D96, D113, D130, D147, D164, D181, D198, D215, K11, K28, K45, K62, K79, K96, K113, K130, K147, K164, K181, K198, K215, R11, R28, R45, R62, R79, R96, R113, R130, R147, R164, R181, R198, R215, Y11, Y28, Y45, Y62, Y79, Y96, Y113, Y130, Y147, Y164, Y181, Y198, Y215,AF11, AF28, AF45, AF62, AF79, AF96, AF113, AF130, AF147, AF164, AF181, AF198, AF215")
If FemCare.Value <> "" Then
Y = Y + 1
FemCare.Value = "FemCare" & Y
End If
Next FemCare
Exit For
'And additional code for Youth1 Youth2 Youth3 OtherAdult cut for posting brevity
Next sh
End Sub
Stephanie, Is this what you are trying?
Sub DelConfSAVE()
Dim sh As Worksheet
Dim X As Long, Y As Long, i As Long
For Each sh In Worksheets(Array("Oct-Dec Attendance", "Jan-Mar Attendance", _
"Apr-Jun Attendance", "Jul-Sep Attendance"))
X = 0
For i = 11 To 215 Step 17
With sh
'~~> Male
If Not Len(Trim(.Range("C" & i).Value)) = 0 _
Then .Range("C" & i).Value = "MaleCare" & X
If Not Len(Trim(.Range("J" & i).Value)) = 0 _
Then .Range("J" & i).Value = "MaleCare" & X
If Not Len(Trim(.Range("Q" & i).Value)) = 0 _
Then .Range("Q" & i).Value = "MaleCare" & X
If Not Len(Trim(.Range("X" & i).Value)) = 0 _
Then .Range("X" & i).Value = "MaleCare" & X
If Not Len(Trim(.Range("AE" & i).Value)) = 0 _
Then .Range("AE" & i).Value = "MaleCare" & X
'~~> Female
If Not Len(Trim(.Range("D" & i).Value)) = 0 _
Then .Range("D" & i).Value = "FemCare" & Y
If Not Len(Trim(.Range("K" & i).Value)) = 0 _
Then .Range("K" & i).Value = "FemCare" & Y
If Not Len(Trim(.Range("R" & i).Value)) = 0 _
Then .Range("R" & i).Value = "FemCare" & Y
If Not Len(Trim(.Range("Y" & i).Value)) = 0 _
Then .Range("Y" & i).Value = "FemCare" & Y
If Not Len(Trim(.Range("AF" & i).Value)) = 0 _
Then .Range("AF" & i).Value = "FemCare" & Y
X = X + 1: Y = Y + 1
End With
Next i
'And additional code for Youth1 Youth2 Youth3 OtherAdult cut for posting brevity
Next sh
End Sub

Resources