2

I am scraping a website with credentials and I have to click an element (button) that exports a pdf file (not as save as window).

The button directly exports the pdf file to C:\Users\User\Downloads.

How can I change the directory to the desktop instead?

Also how to rename the file?

The code used to click this button

On Error Resume Next
Do While .FindElementByXPath("//*[@id='theBttnbobjid_1545645103945_dialog_submitBtn']") Is Nothing
    DoEvents
Loop
On Error GoTo 0
.FindElementByXPath("//*[@id='theBttnbobjid_1545645103945_dialog_submitBtn']").Click

This is the html related to that button

<tbody><tr valign="middle"><td height="21" width="5" style="background-image:url('aspnet_client/system_web/4_0_30319/crystalreportviewers13/js/crviewer/../dhtmllib/images/skin_standard/button.gif');background-position:0px 0px;"></td><td id="theBttnCenterImgbobjid_1545648005071_dialog_submitBtn" align="center" class="wizbutton" style="padding-left:3px;padding-right:3px;background-image:url('aspnet_client/system_web/4_0_30319/crystalreportviewers13/js/crviewer/../dhtmllib/images/skin_standard/button.gif');background-position:0px -42px;"><nobr><a id="theBttnbobjid_1545648005071_dialog_submitBtn" href="javascript:void(0)" class="wizbutton" role="button">Export</a></nobr></td><td height="21" width="5" style="background-image:url('aspnet_client/system_web/4_0_30319/crystalreportviewers13/js/crviewer/../dhtmllib/images/skin_standard/button.gif');background-position:0px -21px;"></td></tr></tbody>
Community
  • 1
  • 1
YasserKhalil
  • 9,138
  • 7
  • 36
  • 95
  • 2
    Usual question.... is there an url associated with the download? – QHarr Dec 24 '18 at 10:23
  • Thanks a lot for reply. I have attached the html part. I think it is java script too – YasserKhalil Dec 24 '18 at 10:41
  • Can you share the url @YasserKhalil? I think there is a way to download and save those files in desktop without even knowing the exact address of the path. – SIM Dec 24 '18 at 11:49

1 Answers1

1

You specify the default download at the start with SetPreference. You could then rename the file by finding the latest modified file in that folder (in this case I use file system object with .csv mask)

If you have an actual URL for download then use URLMon or binary download.

Option Explicit
Public Sub SpecifyDownloadFolder()
    Dim d As WebDriver, filename As String, myFolder As Object
    Const URL = "https://www.stats.govt.nz/large-datasets/csv-files-for-download/"
    Const DOWNLOAD_DIRECTORY As String = "C:\Users\User\Downloads"
    Const FILE_NAME As String = "myNewCsv.csv"
    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")   
    Set d = New ChromeDriver
    With d
        .SetPreference "download.default_directory", DOWNLOAD_DIRECTORY
        .SetPreference "download.directory_upgrade", True 'safeguard
        .SetPreference "download.prompt_for_download", False 'safeguard
        .get URL
        .FindElementByCss("h3 [download]").Click
        Application.Wait Now + TimeSerial(0, 0, 5)
        d.Quit
    End With

    Set myFolder = fso.GetFolder(DOWNLOAD_DIRECTORY)

    Dim objFile As Object, dteFile As Date

    dteFile = DateSerial(1900, 1, 1)
    For Each objFile In myFolder.Files
        If objFile.DateLastModified > dteFile And fso.GetExtensionName(objFile.Path) = "csv" Then
            dteFile = objFile.DateLastModified
            filename = objFile.NAME
        End If
    Next objFile
    If filename <> vbNullString And Not fso.FileExists(DOWNLOAD_DIRECTORY & "\" & FILE_NAME) Then
       fso.MoveFile DOWNLOAD_DIRECTORY & "\" & filename, DOWNLOAD_DIRECTORY & "\" & FILE_NAME
    End If
End Sub
QHarr
  • 83,427
  • 12
  • 54
  • 101
  • 1
    more robust would be to see if you can grab the file name from the html and use that when you do the MoveFile at the end. Is the filename of the download present in the html? – QHarr Dec 24 '18 at 19:22
  • As for this line `Application.Wait Now + TimeSerial(0, 0, 5)`, I think it is to wait till the file is downloaded completely .. Is there another approach to check for the completeness of the downloading process then to resume the code? – YasserKhalil Dec 25 '18 at 01:19
  • 1
    You could loop the download folder looking for a change in file count – QHarr Dec 25 '18 at 08:37
  • Thanks a lot. I already worked on that idea. Thank you very much – YasserKhalil Dec 25 '18 at 09:03
  • 1
    yeah I have just seen your posted question. As usual, remember to include timed loop (probably time to convert that loop into a function returning a boolean, or just a separate timer sub) to prevent possible infinite loop. Consider any error handling for file locking as downloading to a folder at the same time monitoring it can have some unexpected consequences. Partly why I had to abandon my original answer using command line. – QHarr Dec 25 '18 at 09:08