Download zipped csv file after extracting it - excel

I have the url which contains a zipped csv file, I need to download only .csv from the zip , the Codes below is downloading zip
Sub DownloadFile()
Dim myURL As String
myURL = "https://www1.nseindia.com/content/historical/EQUITIES/2020/FEB/cm07FEB2020bhav.csv.zip"
Dim WinHttpReq As Object
Set WinHttpReq = CreateObject("Microsoft.XMLHTTP")
WinHttpReq.Open "GET", myURL, False, "username", "password"
WinHttpReq.send
If WinHttpReq.Status = 200 Then
Set oStream = CreateObject("ADODB.Stream")
oStream.Open
oStream.Type = 1
oStream.Write WinHttpReq.responseBody
oStream.SaveToFile "C:\Users\playt\Desktop\STACK\ruff.zip", 2 ' 1 = no overwrite, 2 = overwrite
oStream.Close
End If
End Sub

You cannot download a file from an archive, but you can adapt your code in the next way:
Insert this lines at the end of your existing code (just before End Sub):
Dim zipFileName As String, unZipFolderName As String
zipFileName = "C:\Users\playt\Desktop\STACK\ruff.zip"
unZipFolderName = left(zipFileName, InStrRev(zipFileName, "\") - 1)
UN_Zip zipFileName, unZipFolderName
The simplest sub able to unzip and delete the archive must look like that (it needs a reference to 'Microsoft Shell Controls And Automation'):
Private Sub UN_Zip(zipFileName As String, unZipFolderName As String)
Dim wShApp As New Shell
wShApp.Namespace(unZipFolderName).CopyHere wShApp.Namespace(zipFileName).Items
Kill zipFileName
End Sub
If too lazy for adding the reference, to make the code look more elegant, the sub can be adapted with only two lines:
Use Dim wShApp As Object instead of Dim wShApp As New Shell declaration and then add the next line:
Set ShApp = CreateObject("Shell.Application")
In this way, no reference is necessary, anymore...

Related

ADODB Stream convert binary to string

I'm facing a problem when trying to open a file from a URL using ADODB, and then using that as a string stream. Basically, the issue I'm facing is almost a duplicate of this question here:
convert ADODB binary stream to string vba
Except that I have to use an ADODB Stream to work with the content later on. Therefore, skipping ADODB completely is not an option, like in the answer in the other topic.
Right now, what I'm doing is making a HTTP GET Request, using a binary stream to save it as a file, then loading that very same file using a text stream. This works just fine, but there has to be a way to skip the saving-loading part and make it work directly.
Here is the code I have so far:
Dim myURL As String
myURL = "https://xyz.xyz/xyz.csv"
Dim WinHttpReq As Object
Set WinHttpReq = CreateObject("Microsoft.XMLHTTP")
WinHttpReq.Open "GET", myURL, False
WinHttpReq.Send
Dim objStream, strData
Dim leftcellstarttemp As Variant, rightcellstarttemp As Variant, leftcellendtemp As Variant, rightcellendtemp As Variant, r As Long, line As String, dtStr As String, mlValue As String, dtArr() As String
myURL = WinHttpReq.ResponseBody
If WinHttpReq.Status = 200 Then
Set oStream = CreateObject("ADODB.Stream")
oStream.Open
oStream.Type = 1
oStream.Write WinHttpReq.ResponseBody
oStream.SaveToFile "C:\Temp\file1.csv", 2
oStream.Close
Set objStream = CreateObject("ADODB.Stream")
objStream.Charset = "utf-8"
objStream.Type = 2
objStream.Open
objStream.LoadFromFile "C:\Temp\file1.csv"
line = objStream.ReadText(-2)
End If
Do Until objStream.EOS
(and so on, and so forth...)
Can you help me on how I can get past this needless file saving-loading process?
Thanks!

VBA Code Running in debugging mode but not in runtime

Public myHTTP As MSXML2.XMLHTTP60
Sub SendXML()
Dim response As String
Dim MyXmlHttpHandler As CXMLHTTPHandler
Dim myxml As String
Dim a As String
Dim URL2 As String
Dim FSO As Object
Dim NewFile As Object
Dim XMLFileText As String
If Not myHTTP Is Nothing Then Set myHTTP = Nothing
Set myHTTP = New MSXML2.XMLHTTP60
Set MyXmlHttpHandler = New CXMLHTTPHandler
MyXmlHttpHandler.Initialize myHTTP
myHTTP.OnReadyStateChange = MyXmlHttpHandler
myxml = "D:\1.xml"
myHTTP.Open "get", myxml, True
myHTTP.send (myxml)
a = myHTTP.responseText
URL2=Workbooks("MainSheet.xlsm").Worksheets("OTHERS").Range("I2").Value
If Workbooks("MainSheet.xlsm").Worksheets("OTHERS").Range("h2").Value = vbNullString Or Workbooks("MainSheet.xlsm").Worksheets("OTHERS").Range("h3").Value = vbNullString Then
MsgBox "User not defined server database address or port number...!!!" & vbNewLine & " Failed.."
Exit Sub
End If
myHTTP.Open "POST", URL2, True
myHTTP.send (a)
Set FSO = CreateObject("Scripting.FileSystemObject")
Set NewFile = FSO.CreateTextFile("D:\response.XML", 1, 1)
XMLFileText = ""
NewFile.write (XMLFileText & myHTTP.responseText & vbNewLine) ‘---------error occurred here not printing my response.text in new file.
End Sub
I have already tried on error resume next, it just printing a blank file.
I have also tried on error goto errorhandler
but it also failed saying runtime error dialoge box....
I just want to save response text in a xml file without any error dialouge box..
For future readers
Change the last argument from True to False
myHTTP.Open "POST", myxml, False
Allow time for completion
Is this a large file? Why use async wrapper this way? Why not simple xmlhttp POST request with False argument? – QHarr 8 mins ago
this comment solved my error..... thnks

VBA Error on Namespace().CopyHere...and...Namespace().items

I'm attempting to modify a VBA script from another post (26486871).
The script will download a Zip file, extract a text file and import the data to Excel.
I don't know VBA so I'll tackle each of the functions one at-a-time.
Create a temp directory with a randomized name................................Complete
Download a Zip file from a public server...............................................Complete
Extract the text file (20MB, tab-delimited)..............................................Error
Import the data into the open worksheet (overwrite the existing data)...Not Yet
On the Extract portion, I'm receiving a run-time error on the following line:
objOApp.Namespace(FileNameToUnzip).CopyHere objOApp.Namespace(varFileNameFolder).items, 256
"Run-time error '91: Object variable or With block variable not set."
When I hover my cursor over the variables while in Debug Mode, the directory and filenames are correct.
I'm unsure what is not set. I appreciate any help.
Option Explicit
'Main Procedure
Sub DownloadExtractAndImport()
Dim url As String
Dim targetFolder As String, targetFileZip As String, targetFileTXT As String
Dim wkbAll As Workbook
Dim wkbTemp As Workbook
Dim sDelimiter As String
Dim newSheet As Worksheet
url = "http://www.example.com/data.zip"
targetFolder = Environ("TEMP") & "\" & RandomString(6) & "\"
MkDir targetFolder
targetFileZip = targetFolder & "data.zip"
targetFileTXT = targetFolder & "data.txt"
'1 download file
DownloadFile url, targetFileZip
'2 extract contents
Call UnZip(targetFileZip, targetFolder)
End Sub
Private Sub DownloadFile(myURL As String, target As String)
Dim WinHttpReq As Object
Dim oStream As Object
Set WinHttpReq = CreateObject("Msxml2.ServerXMLHTTP")
WinHttpReq.Open "GET", myURL, False
WinHttpReq.send
myURL = WinHttpReq.responseBody
If WinHttpReq.Status = 200 Then
Set oStream = CreateObject("ADODB.Stream")
oStream.Open
oStream.Type = 1
oStream.Write WinHttpReq.responseBody
oStream.SaveToFile target, 1 ' 1 = no overwrite, 2 = overwrite
oStream.Close
End If
End Sub
Private Function RandomString(cb As Integer) As String
Randomize
Dim rgch As String
rgch = "abcdefghijklmnopqrstuvwxyz"
rgch = rgch & UCase(rgch) & "0123456789"
Dim i As Long
For i = 1 To cb
RandomString = RandomString & Mid$(rgch, Int(Rnd() * Len(rgch) + 1), 1)
Next
End Function
Private Function UnZip(PathToUnzipFileTo As Variant, FileNameToUnzip As Variant)
Dim objOApp As Object
Dim varFileNameFolder As Variant
varFileNameFolder = PathToUnzipFileTo
Set objOApp = CreateObject("Shell.Application")
objOApp.Namespace(FileNameToUnzip).CopyHere objOApp.Namespace(varFileNameFolder).items, 256
End Function
Dim mainFolder As String
Dim zipFolder As String
Dim destinationFolder As String
Dim oShell As Object
Dim oMainFolder As Object
Dim oDestinatioFolder As Object
Dim oZipFolder As Object
Dim oZipItems As Object
replace with
Dim mainFolder As Variant
Dim zipFolder As Variant
Dim destinationFolder As Variant
Dim oShell As Object
Dim oMainFolder As Object
Dim oDestinatioFolder As Object
Dim oZipFolder As Object
Dim oZipItems As Object
Comintem is right, you should edit your old question with the added code rather than post a near identical new question. Perhaps keep this question and delete the old one.
To answer your question, it looks as if you're passing your arguments in the wrong order to your UnZip function. Try changing the line to:
Call UnZip(targetFolder, targetFileZip)
Update
It's difficult to diagnose the issues as your objects are being created and its properties/methods being called all on one line. Judging by the nature of your questions it doesn't seem as though your VBA knowledge is particularly vast and that you're trying to construct a working solution by tying various pieces of web code together. It's not my position to judge that kind of approach but my advice would be, if you take this approach, to create your objects one at a time and call its methods one at a time. This will make it far easier to diagnose your code.
I've tried to rewrite elements of your code to show you how this could be done. It might be a bit overkill but at least it'll help you identify the precise location of any problems. Obviously change the folder names to your own.
Dim mainFolder As String
Dim zipFolder As String
Dim destinationFolder As String
Dim oShell As Object
Dim oMainFolder As Object
Dim oDestinatioFolder As Object
Dim oZipFolder As Object
Dim oZipItems As Object
'Define the folder names
mainFolder = "C:\Users\User\Downloads\SO\" 'change to your own folder name
zipFolder = "sqlite-shell-win32-x86-3071700.zip" 'an old sqlite download = change to your name
destinationFolder = Left(zipFolder, Len(zipFolder) - 4) 'name of zip folder minus the '.zip'
'Create the new destination folder
MkDir mainFolder & destinationFolder
'Acquire the folder items
'create the shell object
Set oShell = CreateObject("Shell.Application")
'create the main folder object as Folder3 item
Set oMainFolder = oShell.Namespace(CVar(mainFolder)) 'argument must be a variant
'create the destination folder object as Folder3 item
Set oDestinatioFolder = oMainFolder.Items.Item(CVar(destinationFolder & "\")).GetFolder
'create the zip folder object as Folder3
Set oZipFolder = oMainFolder.Items.Item(CVar(zipFolder)).GetFolder
'Extract the zip folder items and write to desination folder
oDestinatioFolder.CopyHere oZipFolder.Items, 256

Extract from a Dropbox account with Excel VBA

I am attempting to pull data from a Dropbox account with Excel VBA.
I removed the URL to make the generic script easier to follow:
Sub DownloadFile()
Dim myURL As String
myURL = "Some URL HEre"
Dim WinHttpReq As Object
Set WinHttpReq = CreateObject("Microsoft.XMLHTTP")
WinHttpReq.Open "GET", myURL, False, "username", "password"
WinHttpReq.send
myURL = WinHttpReq.responseBody
If WinHttpReq.Status = 200 Then
Set oStream = CreateObject("ADODB.Stream")
oStream.Open
oStream.Type = 1
oStream.Write WinHttpReq.responseBody
oStream.SaveToFile "C:\Users\Eric\Downloads\Miami.txt", 2 ' 1 = no overwrite, 2 = overwrite
oStream.Close
End If
End Sub
My original URL is the Dropbox URL, which includes the text file in the sub directories (..../..../somefile.txt). I do not know what to do for the username and password options, and left those untouched when I originally ran the file.
When I did run the code, I had success, however I had a mass amount of HTML code pulled and not the text file downloaded.

Changing Contents of Select tag on a webpage using excel vba (To download CSV files from the webpage)

I am trying to download all the csv files from a specific website by using excel vba
Following is the code i have prepared :
Sub Gettable()
Dim URL As String
Dim ie As Object
Dim ieDoc As Object
Dim sel_day As Variant
URL = "http://www.bseindia.com/markets/equity/EQReports/BhavCopyDebt.aspx?expandable=3"
Set ie = CreateObject("InternetExplorer.Application")
ie.Visible = True
ie.navigate URL
Do Until (ie.readyState = 4 And Not ie.Busy)
DoEvents
Loop
Set ieDoc = ie.document
'============================================================================
ieDoc.getElementsByTagName("Select")("fdate1").Options("02").SelectIndex
'============================================================================
'ie.Quit
'Set ie = Nothing
'Set ieDoc = Nothing
End Sub
Now the problem i am facing here is i am not able to change the contents dropdown box(to form a date).
I have already tried lots of solutions from stackoverflow as well as other websites but havent got any success. i have good programming knowledge but am stuck at this point the whole day. Any help would be appreciated. thanks in advance :)
All i wanted in the end was to download all csv files. I figured out an alternative solution in the mean time to download the csv file but would still appreciate if someone gives a solution to this issue i had posted above... :)
My alternative Solution as follows :
Sub try10() 'Took me 10 tries by the way :)
Dim NoOfDays As Long, i As Long
Dim MyDate As Variant
'Since the minimum date can't be less #1/1/2007# so lets loop until Mydate reaches #1/1/2007#.
NoOfDays = Date - #1/1/2007#
For i = 0 To NoOfDays
MyDate = Format((Date - i), "ddmmyy")
Dim myURL As String
myURL = "http://www.bseindia.com/download/BhavCopy/Equity/eq" & MyDate & "_csv.zip"
Dim WinHttpReq As Object
Set WinHttpReq = CreateObject("Microsoft.XMLHTTP")
WinHttpReq.Open "GET", myURL, False
WinHttpReq.Send
myURL = WinHttpReq.ResponseBody
If WinHttpReq.Status = 200 Then
Set oStream = CreateObject("ADODB.Stream")
oStream.Open
oStream.Type = 1
oStream.Write WinHttpReq.ResponseBody
oStream.SaveToFile ("C:\Users\X\Desktop\BhavCopies\eq" & MyDate & "_csv.zip")
oStream.Close
End If
Next
End Sub
This solution however produces a 211kb fake file for csv's that don't exist which can be dealt with manually . :) ;)
The items you are trying to control are in an iframe. To get to the HTML inside the iframe, extract the src attribute from the tag and navigate to the URL formed by that src and the base URL. In this case the src is "Equitydebcopy.aspx", so if you navigate to "http://www.bseindia.com/markets/equity/EQReports/Equitydebcopy.aspx" you'll find that the following lines will allow you to get the information you want.
ie.document.getElementByID("fdate1").Value = "15"
ie.document.getElementByID("fmonth1").Value = "1"
ie.document.getElementByID("fyear1").Value = "2014"
ie.document.getElementByID("btnSubmit").Click

Resources