How do I reference to another (open or closed) workbook, and pull values back, in VBA? - Excel 2007 - vba

Basically I need to gather a fair few figures from another workbook (Which is found and can be opened by a UserForm, therefore the location and names are variable). I need to use VBA for this as I also need to populate a chart with this data. I would prefer to not have to open the other workbook in order to do it, but if it is far easier then its OK.
The UserForm is done and works fine, and I have the code I need to populate the chart, however I can't get VBA to pull back the data from the other workbook and assign it to the variables that I need it to.
Any ideas on how I can get VBA to do this? It would be greatly appreciated.

You will have to open the file in one way or another if you want to access the data within it. Obviously, one way is to open it in your Excel application instance, e.g.:-
(untested code)
Dim wbk As Workbook
Set wbk = Workbooks.Open("C:\myworkbook.xls")
' now you can manipulate the data in the workbook anyway you want, e.g. '
Dim x As Variant
x = wbk.Worksheets("Sheet1").Range("A6").Value
Call wbk.Worksheets("Sheet2").Range("A1:G100").Copy
Call ThisWorbook.Worksheets("Target").Range("A1").PasteSpecial(xlPasteValues)
Application.CutCopyMode = False
' etc '
Call wbk.Close(False)
Another way to do it would be to use the Excel ADODB provider to open a connection to the file and then use SQL to select data from the sheet you want, but since you are anyway working from within Excel I don't believe there is any reason to do this rather than just open the workbook. Note that there are optional parameters for the Workbooks.Open() method to open the workbook as read-only, etc.

Related

VBA - When to specify ActiveWorkbook

When writing VBA code, if you know you're going to be operating in the same workbook and on a certain worksheet, should you specify ActiveWorkbook for the workbook objects in your code there?
Example:
ActiveWorkbook.Sheets("Sheet1").Range("$A$1")
vs
Range("$A$1")
Above code assumes you are working off of Sheet1 through local macros(under Sheet1 object in VBA).
Better than using ActiveWorkbook in most situations is using WorkBooks("Book1") This is more specific and robust and I believe faster to execute than activating a workbook and then pointing to it when referencing ranges.
The VBA will default to the last active workbook if you do not designate one when using lines of code like Range("A1") So if you are working in just one workbook it is not necessary since the last active workbook should always be the workbook you want the code to execute in. I typically only designate sheets and ranges when I'm working in a single workbook since it is a little redundant to tell excel to select the active workbook when it already does by default in the absence of a specific workbook designation.
Just make sure that you will be running the macro from the open workbook that you want the code to execute in.
Including a workbook designation will never hurt and it will make your code more robust. But if you will only ever have the code execute in a single workbook it is not necessary.

Open new workbook, and run macro, using button

I have a workbook that runs a large multitude of macros, all based on which button is clicked.
I need one of the macro to open a new workbook, and import two files into the workbook (that part I can do).
The second part is that I need it to run a particular macro, in the new workbook. The macro would be stored in the original workbook.
I've seen some suggestions that I need to use APPLICATION.RUN, which has the parameters of having to choose a workbook and name of the routine.
Does this method work?
Assuming it does:
For the workbook, do I need to specify the file path, or just the workbook name?
For the macro, do I need to make the macro public?
Do I need to specify the module it is in?
Are there any other parameters I need to specify to get this method to work?
Is there another method that might work, if APPLICATION.RUN does not work?
What you need to use is :
Application.Run "'FileName.xlsm'!MacroName", "Parameters"
You don't need to specify the path if your workbook is already open, you don't need to specify the module as you can't have doubloons names for different procedures, and there are no other parameters needed.
The procedure doesn't need to be public (let me know if it does), and for alternative methods in VBA, there is none (as the Call method only work in the same workbook), but there are some in VB if this doesn't work out.
Here is a very short example that you can adapt:
Sub demo()
Dim Original As Workbook
Dim Created As Workbook
Set Original = ThisWorkbook
' create a new workbook
Workbooks.Add
Set Created = ActiveWorkbook
' go back
Original.Activate
'make a change in the newly created workbook
Created.Sheets("Sheet1").Range("A1").Value = "whatever"
' save the newly created workbook
Created.Save
Created.Close
End Sub

Excel VBA - Formatting script for automation

So here's what I'm trying to do:
Open file: Pc_Profile
Create new sheet: Sheet1
Copy desired cells from Pc_Profile to Sheet1 (see script below)
Copy entire Sheet1 to new excel file: db.xls
Rename sheet to content of cell A5
Create new sheet for next script run
Basically I'm trying to automate an extraction of a TON of excel files into a single organized file. Each script call should extract to its own sheet so there's no overwritten information.
Here is what I have working so far. It just copies the desired cells to a new sheet within the same file.
' Create Excel object
Set objExcel = CreateObject("Excel.Application")
' Open the workbook
Set objWorkbook = objExcel.Workbooks.Open _
("\\[directory]\Pc_Profile.xls")
' Set to True or False, whatever you like
objExcel.Visible = True
objWorkbook.Worksheets("Pc_Profile").Range("A5:D5").Copy
objWorkbook.Worksheets("Sheet1").Range("A1").PasteSpecial
objWorkbook.Worksheets("Pc_Profile").Range("A8:B8").Copy
objWorkbook.Worksheets("Sheet1").Range("A2").PasteSpecial
objWorkbook.Worksheets("Pc_Profile").Range("A13:B13").Copy
objWorkbook.Worksheets("Sheet1").Range("A3").PasteSpecial
objWorkbook.Worksheets("Pc_Profile").Range("A15:D17").Copy
objWorkbook.Worksheets("Sheet1").Range("A4").PasteSpecial
objWorkbook.Worksheets("Pc_Profile").Range("A24:E26").Copy
objWorkbook.Worksheets("Sheet1").Range("A7").PasteSpecial
objWorkbook.Worksheets("Pc_Profile").Range("A28:B30").Copy
objWorkbook.Worksheets("Sheet1").Range("A10").PasteSpecial
objWorkbook.Worksheets("Pc_Profile").Range("A43:B43").Copy
objWorkbook.Worksheets("Sheet1").Range("A13").PasteSpecial
objWorkbook.Worksheets("Pc_Profile").Range("A45:B45").Copy
objWorkbook.Worksheets("Sheet1").Range("A14").PasteSpecial
' Activate Sheet2 so you can see it actually pasted the data
objWorkbook.Worksheets("Sheet2").Activate
I would really appreciate the extra push. I'm automating this for a work project and have no experience with VB - I just learned that on the go.
A couple things that are good practice to get into before I get to your actual question:
1) Any macro that you expect to run a long time should have Application.ScreenUpdating = False before any actual work is done in the code, this tells Excel not to bother with changing what's displayed on the screen (big performance booster). Be sure to include an Application.ScreenUpdating = True near the end of your code
2) Similar to #1, you generally want to include Application.Calculation = xlManual to boost performance. If you have large ranges of cells that your macro needs accurate up-to-date values from, it may be easier to leave the calculation automatic, but that doesn't appear to be the case in this instance.
3) You don't need to create a new Excel instance (which is what your first line of code does). You're already in a perfectly good instance of Excel. This also saves you having to close the other instance at the end of the macro (or worse from forgetting to do so and having memory get hogged by Excel processes that aren't really in use)
As to your specific problem, it sounds like you have more workbooks that Pc_profile to copy from, and that you're wanting to create a new "db.xls" with each run of the macro. Based on those assumptions all you need to do is nest your code starting with 'Open the workbook and objWorkbook.Worksheets("Sheet1").Range("A14").PasteSpecial inside a Do While loop. The thing I'm not sure about is how to control the loop. If the list of files is always the same, you should just include a list on a sheet in the workbook that holds the macro and just iterate through that.
The other thing you should do for ease of coding, and to make the loop more effective is declare and use a Worksheet variable and set if for each workbook to the appropriate sheet to pull data from. Ex.
Dim ws as Worksheet
'The Dim is outside your loop, but this would be inside it
Set ws = objWorkbook.Worksheets("whatever_the_sheet's_name_is")
This way you can replace each occurrence of objWorkbook.Worksheets("Pc_Profile"). with ws., easier to type, easier to read, easier to update, and less error prone.
Next, you don't actually have code for moving Sheet1 to a new workbook, or renaming it. To move it (as well as the other Sheet1's yet to be created), you should, before getting to the Do While loop, have the following
Dim target as Workbook
Set target = Application.Workbooks.Add
Then at almost the end of the loop, you need objWorkbook.Worksheets("Sheet1").Move Before:=Target.Sheets(1)
Last, you need to include objWorkbook.Close SaveChanges:=False after you've moved Sheet1 out of the Pc_Profile and renamed it.

Where Exactly To Store VBA

We receive Excel files daily from our field offices which I have to clean and re-format (about 110 columns and 500 rows-worth) using VBA.
I need to save my VBA as a macro so we can use it to clean up all the workbook we receive by running the macro and saving the edited sheet as a new worksheet by getting the name from UserForm Combobox items.
Where exactly should I store the VBA snippets? I mean when I open the Visual Basic panel, I have these three options:
Running The Code From Microsoft Excel Object :Sheets1(Sheet1)
Running the Code From An Inserted Module
Running the Code From User Form
If I am supposed to use options 1 or 2, how can I call the UserForm for saving the sheet?
I Recomend you to use modules (Option B)
Option C goes with option B, ill explain, you can create a sub in a module in option B, then you can do:
UserForm1.show
In Option B I would writte this code, but before trying this i recomend you to understand a bit more of vba
sub ClearWBs()
'opening workbook
Workbooks.Open Filename:="c:\book1.xls"
'your code
'your code
'below code for saving and closing the workbook
Workbooks("book1.xls").Activate
ActiveWorkbook.Save
ActiveWorkbook.Close
end sub
Use Module:
If your VBA code focusses on data summarization and manipulation I suggest you use a Module.(example is what you have described in your question).
Use Form:
If what you wan't to do requires a GUI(Graphical User Interface) then you'll have to resort to Form where you can design your GUI. (example is if you have many fields that the user needs to fill-up with distinct values in which you provide the choices)
Use Excel Object:
If what you wan't to do has something to do with events happening on Worksheet and/or Workbook, like for example whenever you add sheet the macro runs, or when you open or close the workbook the macro runs then you will have to write the macro in the Excel Object.
This is basically what i have in mind, hope this helps.
If you receive files that do not contain VBA and you need to apply the same code on those files all the time then I propose that you either save that code in your personal workbook.
You can see how to do that here: http://office.microsoft.com/en-ca/excel-help/copy-your-macros-to-a-personal-macro-workbook-HA102174076.aspx
This is nice because you can also tie it to keyboard shortcut or just have it always ready for you to use.
The disadvantage is that it will only be set up per user session per computer. What you can do is have that code all set up in a module and then import it into your personal workbook if you change session or if someone else has to do it.
Once it's done, you will not have to include the module in your files your receive again.

Vb.net Updating excel formula with references to other workbooks

I am trying to update some formulas from one workbook, to another workbook. Everything is working great until I run into a formula that has a reference to another workbook. For example a formula like this =IF(ISERROR(W!Var1),0,W!Var2) It will prompt me to open this workbook, I am assuming so that it can evaluate the formula. So my question is this. Is there a way for me to handle these situations on the fly, so if there is a workbook reference needed it will prompt me and then save it to memory? Because if I have more than one cell that contains these formulas it will prompt me to open the referenced workbook for every cell that contains the link. Alternatively, is there a way that I can just push my formula into the cell without having excel evaluate it?
So in my code I have this line which works for any value that doesn't contain a workbook reference. TheRange.RefersToRange.FormulaR1C1 = RangeFormula
Any help is greatly appreciated.
I understand that you refer to Worksheets (each of the "tabs" in a given Excel file), the Workbook is the whole file. The popping-up message appears when the referred Worksheet cannot be found. Example: range.Value = "=sheet5!A3" (in a Workbook having just "sheet1", "sheet2" and "sheet3"). If you want to avoid this message (although bear in mind that the Worksheet is not there and thus the calculations will be wrong anyway), you can write:
excelApp.DisplayAlerts = False
Where excelApp is the Excel.Application you are currently using.