Good Day everyone. I'm new to VBA and was working with the following code to figure out how to query multiple tables. I would like the code to go to 100000 rows but I wanted to see how far it could actually run. Sadly, after the 29714th row, it gave me : Run-Time error 1004 'Application-defined or object-defined error'. I don't have a clue as to what is wrong other than the loop parameters might be too big. Any ideas?
Sub Data()
Dim qtb As New QueryTable
Dim url1 As String
Dim i As Long
For i = 2 To 540602 Step 24
url1 = Sheet2.Range("A" & i)
Set qtb = Sheet2.QueryTables.Add(Connection:="URL;" & url1, Destination:=Range("B" & i))
qtb.WebTables = "5"
qtb.FieldNames = True
qtb.RowNumbers = False
qtb.FillAdjacentFormulas = False
qtb.PreserveFormatting = True
qtb.RefreshOnFileOpen = False
qtb.BackgroundQuery = False
qtb.RefreshStyle = xlInsertDeleteCells
qtb.SavePassword = False
qtb.SaveData = False
qtb.AdjustColumnWidth = False
qtb.RefreshPeriod = 0
qtb.WebSelectionType = xlSpecifiedTables
qtb.WebFormatting = xlWebFormattingNone
qtb.WebPreFormattedTextToColumns = True
qtb.WebConsecutiveDelimitersAsOne = True
qtb.WebSingleBlockTextImport = False
qtb.WebDisableDateRecognition = False
qtb.WebDisableRedirections = False
qtb.Refresh BackgroundQuery:=False
Next i
MsgBox ("X")
End Sub
Here's what I came up with. As suggested in the comments, I create the full QueryTable the first time around. After that, I just change the connection to the next cell. The web addresses are now in each row, not every 24. The code steps through them and copies the output to a new sheet for each one. My testing involved only two sites. I don't know how many it will let you create before failing:
Sub Data()
Dim ws As Excel.Worksheet
Dim qtb As QueryTable
Dim url1 As String
Dim i As Long
Set ws = ActiveSheet 'or ws if you prefer
For i = 2 To 3 'links are in each row
url1 = ws.Range("A" & i)
If i = 2 Then
Set qtb = ws.QueryTables.Add(Connection:="URL;" & url1, Destination:=ws.Range("B1"))
With qtb
.WebTables = "5"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.WebSelectionType = xlEntirePage
.WebFormatting = xlWebFormattingNone
.WebPreFormattedTextToColumns = True
.WebConsecutiveDelimitersAsOne = True
.WebSingleBlockTextImport = False
.WebDisableDateRecognition = False
.WebDisableRedirections = False
.Refresh BackgroundQuery:=False
End With
Else
qtb.Connection = "URL;" & url1
qtb.Refresh BackgroundQuery:=False
End If
ws.Copy after:=ws.Parent.Worksheets(ws.Parent.Worksheets.Count)
ActiveSheet.Columns(1).EntireColumn.Delete
Next i
End Sub
Related
I have a function i mostly found on web, to get a table from Google Sheets.
Sub GetDataFromGoogle(wsn As String, address As String)
Dim i As Integer
With Worksheets(wsn)
With .QueryTables.Add(Connection:="URL;" & address, Destination:=.Range("$A$1"))
.PreserveFormatting = False
.BackgroundQuery = True
.WebFormatting = xlWebFormattingNone
.Refresh BackgroundQuery:=False
End With
DoEvents
End With
For i = 1 To ThisWorkbook.Connections.Count
If ThisWorkbook.Connections.Count = 0 Then Exit Sub
ThisWorkbook.Connections.item(i).Delete
i = i - 1
Next i
End Sub
It seems to work well, but as i develloped my data base, a problem happened.
I only get the first 100 entries of my google sheet, then i got a empty line, a strange text on the first next range, and then the line under in position 3 the word List
I have no idea of what it is.
Sub Uygula()
Sheets("Veri").Range("A1:D600").ClearContents
Call GetDataFromGoogle("Veri", "18I8Vddjir3lFvtUorMln4mXlYNsY0KZtBGywVreped4")
End Sub
Sub GetDataFromGoogle(wsn As String, adres As String)
Dim i As Integer
Dim qry As String
Dim myURL As String
qry = Application.EncodeURL("SELECT A, C, G, B")
myURL = "https://docs.google.com/spreadsheets/d/" & adres & "/gviz/tq?tqx=out:csv&sheet=1&tq=" & qry
With Worksheets(wsn)
With .QueryTables.Add(Connection:="TEXT;" & myURL, Destination:=.Range("$A$1"))
.Name = "myTable"
.TextFilePlatform = 65001
.SaveData = False
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.Refresh BackgroundQuery:=False
End With
'DoEvents
End With
'For i = 1 To ThisWorkbook.Connections.Count
'If ThisWorkbook.Connections.Count = 0 Then Exit Sub
'ThisWorkbook.Connections.Item(i).Delete
'i = i - 1
'Next i
End Sub
I need to import an xls file from the web address https://docs.misoenergy.org/marketreports/YYYYMMDD_sr_nd_is.xls where YYYYMMDD is inputed by the user on another worksheet in the same workbook. In the code below nsiday = 20190316 - 1. I don't know how to actually paste the data in the worksheet I want. I am trying to adapt code that grabs a csv file so that it works for the xls file (https://docs.misoenergy.org/marketreports/YYYYMMDD_rt_lmp_final.csv). I hope that makes sense and thank you all for reading/helping! Note: I haven't included the full csv code I'm trying to adapt.
Option Explicit
Sub NSI()
Dim xday As String
Dim todaystamp As String
Dim nsiday As String
Dim MISORTSht As Worksheet
Dim Selection As Range
Set MISORTSht = Sheet3
MISORTSht.Cells.ClearContents
If MISORTSht.QueryTables.Count > 0 Then
MISORTSht.QueryTables(1).Delete
End If
Dim web As Object
Set web = CreateObject("Microsoft.XMLHTTP")
todaystamp = Format(Sheet1.Cells(6, 1).Value, "yyyymmdd")
xday = Format(Sheet1.Cells(1, 1).Value, "yyyymmdd")
'xday is user defined
nsiday = xday - 1
start:
web.Open "GET", "https://docs.misoenergy.org/marketreports/" & nsiday & "_sr_nd_is" & ".xls", False
web.send
If web.Status = "200" Then
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
With MISORTSht.QueryTables.Add(Connection:="URL;https://docs.misoenergy.org/marketreports/" & nsiday & "_sr_nd_is" & ".xls" _
, Destination:=MISORTSht.Range("A1"))
.Name = "NSI_MISO"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = False
.RefreshOnFileOpen = False
.BackgroundQuery = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = False
.RefreshPeriod = 0
.WebSelectionType = xlEntirePage
.WebFormatting = xlWebFormattingNone
.WebPreFormattedTextToColumns = True
.WebConsecutiveDelimitersAsOne = True
.WebSingleBlockTextImport = False
.WebDisableDateRecognition = False
.WebDisableRedirections = False
.Refresh BackgroundQuery:=False
End With
Disregarding the use of QueryTable, you can open online files directly from Excel. Below is an example of how to generate the URL based on a date input and opens it from Excel.
Option Explicit
Private Const DATE_FMT As String = "yyyymmdd"
Private Const BASE_URL As String = "https://docs.misoenergy.org/marketreports/"
Private Const POSTFIX1 As String = "_sr_nd_is.xls"
Private Const POSTFIX2 As String = "_rt_lmp_final.csv"
Sub Main()
Dim dDataDate As Date, dToday As Date, oWB As Workbook
dToday = CDate(ThisWorkbook.Sheets(1).Cells(6, 1).Value) ' Not sure what to do with this
dDataDate = CDate(ThisWorkbook.Sheets(1).Cells(1, 1).Value) - 1 ' 1 day before it
Set oWB = GetOnlineFile(CreateURL1(dDataDate))
If Not oWB Is Nothing Then
' Do whatever you need with the opened file
oWB.Close
Set oWB = Nothing
End If
End Sub
Private Function GetOnlineFile(URL As String) As Workbook
On Error Resume Next
Set GetOnlineFile = Workbooks.Open(URL)
End Function
Private Function CreateURL1(DataDate As Date) As String
CreateURL1 = BASE_URL & Format(DataDate, DATE_FMT) & POSTFIX1
End Function
Private Function CreateURL2(DataDate As Date) As String
CreateURL2 = BASE_URL & Format(DataDate, DATE_FMT) & POSTFIX2
End Function
I want to insert the top x rows from a text file. I can give the number of the StartRow, but is there such parameters where I can give the "EndRow" number to give the top x rows what I want to inseret.
Sub insertTopX()
With ActiveSheet.QueryTables.Add(Connection:= _
"TEXT;C:\Users\HarrsionDavid\Desktop\AnswerForEveryQuestions" _
,Destination:=Cells(1,1))
.Name = "test_file.txt"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileConsecutiveDelimiter = True
.TextFileTabDelimiter = True
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = False
.TextFileSpaceDelimiter = False
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
End Sub
You can read the txt file and split it by new line. Then you would have an array which can be easy to work with.
Sample file:
Read the file and parse it to a variant;
Pass the startRow and the endRow;
Option Explicit
Public Sub TestMe()
Dim filePath As String
filePath = "C:\Users\user\User\nt.txt"
Dim myFile As String
myFile = ReadFileLineByLineToString(filePath)
Dim startRow As Long
Dim endRow As Long
Dim fixedFile As Variant
fixedFile = Split(myFile, vbCrLf)
startRow = 2
endRow = 3
Dim cnt As Long
For cnt = startRow To endRow
Debug.Print fixedFile(cnt - 1)
Next cnt
End Sub
This is the result:
This is the ReadFileLineByLineToString:
Public Function ReadFileLineByLineToString(path As String) As String
Dim fileNo As Long
fileNo = FreeFile
Open path For Input As #fileNo
Do While Not EOF(fileNo)
Dim textRowInput As String
Line Input #fileNo, textRowInput
ReadFileLineByLineToString = ReadFileLineByLineToString & textRowInput
If Not EOF(fileNo) Then
ReadFileLineByLineToString = ReadFileLineByLineToString & vbCrLf
End If
Loop
Close #fileNo
End Function
I am trying to write a loop macro to Excel VBA that takes a flight path from a cell in Sheet 1 (starting at row 1993), inserts the path into a website that calculates the flight data (Great Circle Mapper, shown here: http://www.gcmap.com/), pulls the data from a table on the website into Sheet 2 (starting at row 1996), deletes excess data, and removes "mi" from the miles flown (to leave a numerical value).
My first problem seems to begin with the start of the macro.
While I have defined the counter variable, the cell value variable, and the URL string variable (to concatenate with the cell value variable), debugging shows that only the counter variable gets properly initialized. The cell value variable ("Flight" which is supposed to start at row 1993, column O) does not get initialized, which then causes the URL and name variables not to run properly. Shown here:
ToInfinity = 1993
Flight = Cells(ToInfinity, 15).Value
url = "URL;http://www.gcmap.com/dist?P=" & Flight
name = "dist?P=" & Flight
As for my second problem, on the few times the macro has initialized each variable, the connection argument shown here:
("With ActiveSheet.QueryTables.Add(Connection:= _
url, Flight:=Range("$A$1996:$G$1996"))
Gives me a runtime error, and this block of code is highlighted by the debugger.
The entirety of my code is shown below:
Sub PULLFROMGCM()
'
' PULLFROMGCM Macro
' Pulls data from great circle mapper
'
' Keyboard Shortcut: Ctrl+Shift+T
'
Dim Flight As String
'String variable for each flight path to be analyzed by the website, "Great Circle Mapper"
'
Dim url As String
Dim ToInfinity As Long
' Counter variable for loop, beginning at row 1993 on sheet 1'
Dim name As String
Dim Milesflown As String
ToInfinity = 1993
Flight = Cells(ToInfinity, 15).Value
url = "URL;http://www.gcmap.com/dist?P=" & Flight
name = "dist?P=" & Flight
Do While Not IsEmpty(Cells(ToInfinity, 15))
Sheets("Sheet2").Select
With ActiveSheet.QueryTables.Add(Connection:= _
url, Flight:=Range("$A$1996:$G$1996"))
.CommandType = 0
.name = name
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.WebSelectionType = xlSpecifiedTables
.WebFormatting = xlWebFormattingNone
.WebTables = """mdist"""
.WebPreFormattedTextToColumns = True
.WebConsecutiveDelimitersAsOne = True
.WebSingleBlockTextImport = False
.WebDisableDateRecognition = False
.WebDisableRedirections = False
.Refresh BackgroundQuery:=False
End With
Milesflown = "G:2001"
ActiveCell.Range("A1996:G2000").Select
Selection.QueryTable.Delete
Selection.ClearContents
Sheets("Sheet1").Select
If InStr(Milesflown, "mi") <> 0 Then
Cells(ToInfinity, 11).Value = Left(Milesflown, " ")
End If
ToInfinity = ToInfinity + 1
Loop
End Sub
Link to Excel file from Google Drive
The obvious mistake in your code is that you are not updating the Flight, url and name variables inside your loop.
Correcting the above mistakes, and a few syntax errors (like using ActiveCell instead of ActiveSheet), the following code does what you want.
Sub PULLFROMGCM()
'
' PULLFROMGCM Macro
' Pulls data from great circle mapper
'
' Keyboard Shortcut: Ctrl+Shift+T
'
Dim Flight As String
Dim url As String
Dim ToInfinity As Long
Dim name As String
Dim Milesflown As String
ToInfinity = 1993
Do While Not IsEmpty(Cells(ToInfinity, 15))
' Update the variables in your loop as well
Flight = Cells(ToInfinity, 15).Value
url = "URL;http://www.gcmap.com/dist?P=" & Flight
name = "dist?P=" & Flight
' Calculate how far sheet 2 has rows
Sheets("Sheet2").Select
HowFar = Application.WorksheetFunction.CountA(Range("A:A")) + 3
With ActiveSheet.QueryTables.Add(Connection:= _
url, Destination:=Range("A" & (HowFar + 1) & ":G" & (HowFar + 1)))
.name = name
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.WebSelectionType = xlSpecifiedTables
.WebFormatting = xlWebFormattingNone
.WebTables = """mdist"""
.WebPreFormattedTextToColumns = True
.WebConsecutiveDelimitersAsOne = True
.WebSingleBlockTextImport = False
.WebDisableDateRecognition = False
.WebDisableRedirections = False
.Refresh BackgroundQuery:=False
End With
Milesflown = Range("G" & (HowFar + 6)).Value
ActiveSheet.Range("A" & (HowFar + 1) & ":G" & (HowFar + 5)).Select
Selection.QueryTable.Delete
Selection.ClearContents
Sheets("Sheet1").Select
If InStr(Milesflown, "mi") <> 0 Then
Milesflown = Replace(Milesflown, "mi", "")
Cells(ToInfinity, 12).Value = Milesflown
End If
MsgBox (Milesflown)
ToInfinity = ToInfinity + 1
Loop
End Sub
I am working on a small excel project where I have a user form. The user form has a combo box that has a list of company names retrieved from column (A) in an excel worksheet (This works as expected).
The form has a text box, that depending on the selection from the drop down box returns the stock ticker from column B (Works as expected).
The next step is where it breaks down. The stock ticker value is then passed to a web query that connects to yahoo finance, and retrieves data from the site.
Problem 1:
The web query does not return data until the form is closed. I want it to return the values "instantly."
Problem 2:
Each time I run the query, a new query table is built, even though I have coded my script to delete query tables.
Private Sub cb_Stock_Name_Change()
Set ws = Worksheets("Stock_Info")
With Me
.tb_ticker.Value = ws.cells(.cb_stock_name.ListIndex + 2, 2)
'.TextBox3.Value = Format(Sheet1.cells(.ComboBox1.ListIndex + 7, 9), "0%")
'.TextBox2.Value = Format(Sheet1.cells(.ComboBox1.ListIndex + 7, 10), "0%")
End With
Dim ticker As String
Dim conn As String
Set ws_query = Worksheets("Stock_Query")
ticker = tb_ticker.Value
conn = "URL;http://finance.yahoo.com/q?s=" & ticker
Dim qt As QueryTable
For Each qt In ws_query.QueryTables
qt.Delete
Next qt
Set qt = ws_query.QueryTables.Add _
(Connection:=conn, Destination:=Range("A1"))
With qt
'.Connection = conn
'.Destination = Range("A1")
.WebSelectionType = xlSpecifiedTables
.WebFormatting = xlWebFormattingNone
.WebPreFormattedTextToColumns = True
.WebSelectionType = xlSpecifiedTables
.WebTables = "2"
.Refresh
End With
With Me
.tb_previous_close.Value = ws_query.cells(1, 2)
End With
End Sub
Questions:
What is wrong with my code that is a) doesn't return until my form is closed b) doesn't delete the previous querytable?
Problem 1 - resolved as per the comments (need to put form property as Modeless). You can check MSDN for details on form's mode properties. FYI, by default the forms are modal.
Problem 2 - You need to specify qt's .Name property. Sample this
With qt
.Name = "StockWatch"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = False
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlOverwriteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.WebSelectionType = xlSpecifiedTables
.WebFormatting = xlWebFormattingAll
.WebTables = "2"
.WebPreFormattedTextToColumns = True
.WebConsecutiveDelimitersAsOne = False
.WebSingleBlockTextImport = False
.WebDisableDateRecognition = False
.WebDisableRedirections = False
.Refresh BackgroundQuery:=False
End With
Let me know if this works for you