L.P
L.P

Reputation: 43

VBA : Run a macro FOR another workbook (not from)

I have a workbook (A) in which I have one module with one subroutine. The subroutine downloads an excel file (workbook(B)) from the internet and opens it. The problem I'm faced with is finding a way to execute a subroutine in workbook (B) from the sub in workbook (A).

To reiterate, I have my desired subroutine only in workbook (A) and wish to apply it to workbook (B) by use of the sub in workbook (A).

Note: In my code workbook (B) = Nuance Mobility JIRA.xls and the desired subroutine in workbook (B) that needs to be executed is removeColumns().

My code can be found below :

Public Sub DL()

Dim WebUrl As String
Dim x As Workbook
Dim z As Workbook
Dim nmjexcel As String
Dim xlApp As Excel.Application

' I check to see if the file exists and delete it if it does
nmjexcel = "C:\Users\" & [A2] & "\Downloads\Nuance Mobility JIRA.xls"

If Len(Dir(nmjexcel)) <> 0 Then
    SetAttr nmjexcel, vbNormal
    Kill nmjexcel
End If

'I open chrome and download the file from an URL
WebUrl = [J1]
Shell ("C:\Program Files (x86)\Google\Chrome\Application\chrome.exe -url " & WebUrl)


Application.Wait (Now + TimeValue("0:00:3"))

'I create a new 'hidden' excel app and open workbook (B)
Set xlApp = New Excel.Application
xlApp.Visible = False

Set x = Workbooks.Open("C:\Users\" & [A2] & "\Downloads\Nuance Mobility JIRA.xls")

' I delete some rows, a picture and some columns. 
' It's here that i would like my other subroutine, removeColumns(), to take place !

With x.Sheets("general_report")

    .Rows("1:3").Delete
    .Shapes.Range(Array("Picture 1")).Delete
    .Cells.UnMerge
    .Range("A:A,D:D,E:E,F:F,H:H,I:I,J:J,K:K,L:L,M:M,N:N,O:O,P:P").Delete Shift:=xlToLeft

End With

'Then I copy whats left and paste it into workbook (A)
Set z = ThisWorkbook

Application.ScreenUpdating = False

x.Sheets("general_report").Range("A1").CurrentRegion.Copy

z.Sheets(1).Range("A13").PasteSpecial xlValues


x.Save
x.Application.CutCopyMode = False
x.Close

End Sub

My desired sub to be executed is the following

Sub removeColumns()

Dim rng As Range 'store the range you want to delete
Dim c 'total count of columns
Dim I 'an index
Dim j 'another index
Dim headName As String 'The text on the header
Dim Status As String 'This vars is just to get the code cleaner
Dim Name As String
Dim Age As String
Dim sht As Worksheet

Rows("1:3").Delete


Key = "Key"
Summary = "Summary"
Status = "Status"
Set sht = Sheets("general_report")

sht.Activate 'all the work in the sheet "Incidents"
c = Range("A1").End(xlToRight).Column
'From A1 to the left at the end, and then store the number
'of the column, that is, the last column
j = 0 'initialize the var
For I = 1 To c 'all the numbers (heres is the columns) from 1 to c
    headName = Cells(1, I).Value
    If (headName <> Key) And (headName <> Summary) And (headName <> Status) Then
    'if the header of the column is differente of any of the options
        j = j + 1 ' ini the counter
        If j = 1 Then 'if is the first then
            Set rng = Columns(I)
        Else
            Set rng = Union(rng, Columns(I))
        End If
     End If
Next I
rng.Delete 'then brutally erased from leaf
End Sub

Thank you very much in advance !

Further questions :

1) Is there a way to keep the downloaded excel hidden ?

I have :

Set xlApp = New Excel.Application

xlApp.Visible = False

Set x = Workbooks.Open("C:\Users\" & [A2] & "\Downloads\Nuance Mobility JIRA.xls")

But if i use x= xlApp.Workbooks.Open it gives me an error 'subscript out of range' and highlights :

Set sht = Sheets("general_report")

I tried doing

Dim xlApp as Excel.Application)
...
Set sht = xlApp.Sheets("general_report")

But it gets more errors

2) More generally, is their a way to keep the focus on my workbook (A), so that when chrome downloads the workbook (B) the chrome window doesn't pop up in front ?

Upvotes: 0

Views: 387

Answers (1)

Tim Schmidt
Tim Schmidt

Reputation: 1307

The problem you are facing, occurs because you dont directly address the needed worksheet/workbook, you rather always use the Selected worksheet, which you shouldn´t. It´s unclear and can be done just as simple if directly referring.

To refer to the worbookB I added a parameter to the sub removeColumns, so you can pass the needed workbook.

In the sub then, you just need to use the reference wherever you are working with the worksheet.

So instead of just writing:

somVariable = Cells(1,1).Value 'This always refers to the 'Selected' worksheet

You have to write:

someVariable = myWorkbook.myWorksheet.Cells(1,1).Value

'or to use the parameter wb like i did in your code:

someVariable = wb.Sheets(1).Cells(1,1).Value
'Here the first sheet of this workbook will be used

'You also can use the 'With' statment here:
With wb.Sheets(1)
    someVariable = .Cells(1,1).Value 'Note the dot in font of the 'Cells'
End With

So to use this knowledge in you example, you should try to alter code like following:

/////////////////////////////////////////////////////////////////////////  
Set xlApp = New Excel.Application

xlApp.Visible = False
xlApp.Workbooks.Open("C:\Users\" & [A2] & "\Downloads\Nuance Mobility JIRA.xls")

Set x = xlApp.Workbooks(1)

Call removeColumns(x)

/////////////////////////////////////////////////////////////////////////

Sub removeColumns(ByVal wb As Workbok)

...    

'Always when you are referring to the workbook, you have to use the reference passed as parameter
wb.Sheets("general_report").Rows("1:3").Delete
'In you code the first three rows will always be deleted from the 'Selected' sheet and not the one you are working on later, the 'general_report'
...

Set sht = wb.Sheets("general_report") 

'Also don´t activate() sheet here, youst directly refer to it later
'sht.Activate 'all the work in the sheet "Incidents"

'You can directly refer t it over the variable you created, like this:
c = sht.Range("A1").End(xlToRight).Column
'From A1 to the left at the end, and then store the number
'of the column, that is, the last column

j = 0 'initialize the var
For I = 1 To c 'all the numbers (heres is the columns) from 1 to c
    headName = sht.Cells(1, I).Value
    If (headName <> Key) And (headName <> Summary) And (headName <> Status) Then
    'if the header of the column is differente of any of the options
        j = j + 1 ' ini the counter
        If j = 1 Then 'if is the first then
            Set rng = sht.Columns(I)
        Else
            Set rng = Union(rng, sht.Columns(I))
        End If
     End If
Next I

rng.Delete 'then brutally erased from leaf
End Sub

Hope I could help and if something is still unclear feel free to ask.

Upvotes: 1

Related Questions