How to create a workbook array dynamically in VBA - excel

I am trying to add workbook objects to an array of workbooks
The array is of type public created in a separate module
Option Explicit
Public w() As Workbook
Public i As Integer
then i have the below procedure in a sub stored in a worksheet
Sub test_addwbobjects()
ReDim Preserve w(2)
Application.Workbooks("Quick analysis - Moneycontrol.xlsx").Activate
Set w(i) = ActiveWorkbook
'Set w(i) = Application.Workbooks("Quick analysis - Moneycontrol.xlsx")
i = i + 1
'ActiveSheet.Range("b2") = w(0).Sheets("CF analysis").Range("b2")
'ActiveSheet.Cells(1, 1) = w(i).Sheets("CF analysis").Range("b2")
'ActiveSheet.Range("b2") = w(1).Sheets("CF analysis").Range("b5")
End Sub
Context:
The workbook "Quick analysis - Moneycontrol.xlsx" contains a financial model of a company. I want to be able to compare financial information of multiple companies, so for that purpose I want to create a workbook object every time I paste a company's financials into the "Quick analysis - Moneycontrol.xlsx" workbook
I am currently getting the subscript out of range error.
Can anyone help me with this?
Thanks

Maybe this will help:
Public w As Collection
Sub Test_addWBObject()
Set w = New Collection
w.Add Item:=Workbooks("Quick analysis - Moneycontrol.xlsx"), _
Key:="MyUniqueKeyForThisWorkbook"
'Can use collection as this:
ThisWorkbook.Worksheets("Sheet1").Range("A1") = w(1).Worksheets("Sheet1").Range("C2")
'or this
ThisWorkbook.Worksheets("Sheet1").Range("A1") = w("MyUniqueKeyForThisWorkbook").Worksheets("Sheet1").Range("C2")
'or this
Dim wrkBk As Variant
For Each wrkBk In w
ThisWorkbook.Worksheets("Sheet1").Range("A1") = wrkBk.Worksheets("Sheet1").Range("C2")
Next wrkBk
'or this
Dim x As Long
For x = 1 To w.Count
ThisWorkbook.Worksheets("Sheet1").Range("A1") = w(x).Worksheets("Sheet1").Range("C2")
Next x
End Sub

Related

Get Value and Position of Checkbox in Word Table to Copy Entire Table to Excel

I have a Word file with approximately 10 pages and 20 tables. Some of these tables have checkboxes. I want to copy these tables into an Excel file.
The following code copies all tables from my Word file into my Excel file:
Sub Import()
Option Explicit
Dim wb As Workbook
Dim sh As Worksheet
Dim sheet As Worksheet
Dim lzeile As Integer
Set wb = ActiveWorkbook
Set sh = wb.ActiveSheet
Set sheet = wb.Worksheets("Tabelle1")
Dim Btxt As Object
Set Btxt = CreateObject("Word.Application")
Btxt.Visible = True
Btxt.documents.Open "C:\Users\*.doc" '*=path
lzeile = 0
For i = 1 To 20
Btxt.ActiveDocument.Tables(i).Range.Copy
Application.Goto sheet.Cells(1 + lzeile, 1)
sheet.PasteSpecial Format:="HTML", Link:=False, DisplayAsIcon:=False
lzeile = sheet.Cells(Rows.Count, 1).End(xlUp).Row
lzeile = lzeile + 1
sheet.Cells(lzeile, 1) = "Tabelle" & i
Next i
Btxt.Quit
Set Btxt = Nothing
Set wb = Nothing
Set sh = Nothing
End Sub
It does not copy checkboxes or the value (0 = not checked / 1 = checked) of the checkbox.
I can write the value of a checkbox into a cell in my excel sheet with this line:
sheet.Cells(j, 10) = Btxt.ActiveDocument.Tables(i).FormFields.Item("Kontrollkästchen" & j).Result
With a loop j over all "Kontrollkästchen" (german translation of contentcontrol or formfield item) so basically the name of all formfield items in this Word file.
How can I get the position of these formfield items or identify which formfield item / ContentControl is in which table?
I tried to go through all rows and columns in each table because none of them are larger than 10x10. But I can´t find a way to check if a checkbox is maybe in table 3 on column 5 row 5 and then read the name of this checkbox to a safe the value (0 / 1) in the Excel cell on the same position in my copied table.
The solution depends on whether they're formfields or content controls.
Assuming they're formfields:
Sub Demo()
Dim i As Long, j As Long, Rng As Range
With ActiveDocument
For i = .FormFields.Count To 1 Step -1
With .FormFields(i)
If .Type = wdFieldFormCheckBox Then
j = Abs(.CheckBox.Value)
Set Rng = .Range
.Delete
Rng.Text = j
End If
End With
Next
End With
End Sub
Assuming they're content controls:
Sub Demo()
Dim i As Long, j As Long, Rng As Range
With ActiveDocument
For i = .ContentControls.Count To 1 Step -1
With .ContentControls(i)
If .Type = wdContentControlCheckBox Then
j = Abs(.Checked)
Set Rng = .Range
.Delete
Rng.Text = j
End If
End With
Next
End With
End Sub
For the sake of simplicity and clarity, the sample code below leaves out the parts having to do with Excel, as well as creating the instance of the Word Application. It shows only how to access the Word document's checkboxes and convert those to static values.
At the end, also, the document is closed without saving changes, which means forms protection and the checkboxes should be left intact - the macro will not have affected them.
Note: You should have Option Explicit at the top of the code page, not inside a "Sub".
How it works
The document to be processed is opened and at that moment set to an object (doc). Use this instead of ActiveDocument as it will be much clearer and, in case the user would try to do something, won't affect macro execution.
If the document has forms protection, this must be turned off in order to delete the checkboxes and insert static values.
Then all the form fields are looped. If they are checkboxes, the value is determined, the checkbox removed and the value assigned to the range the checkbox occupied.
After this has completed comes the code to transfer data to Excel. Then the document is closed without saving changes.
Sub ConvertCheckBoxesToValues()
Dim ff As Object ' Word.FormField
Dim doc As Object ' Word.Document
Dim cbValue As String
Dim rngFF As Object ' Word.Range
Set doc = Btxt.Documents.Open("C:\Users\*.doc") '*=path
If doc.ProtectionType <> -1 Then 'wdNoProtection
doc.Unprotect
End If
For Each ff In doc.FormFields
If ff.Type = 71 Then 'wdFieldFormCheckBox
If ff.CheckBox.value = True Then
cbValue = "1"
Else
cbValue = "0"
End If
Set rngFF = ff.Range
ff.Delete
rngFF = cbValue
End If
Next
'Transfer the information to Excel, then
doc.Close 0 'wdDoNotSaveChanges
End Sub

How to name a worksheet?

I have a file (F) that contains several workbooks, each workbook has the same format. I do a conditional sum on each of the workbook under column conditions. I want to put the output within another workbook that contains one worksheet per workbook looped (contained within F).
I cannot find the good strategy to change the worksheet name in function of the looped workbook' name.
Set Output_tot_n = Workbooks("Final_Output").Sheet_name.Range("B7")
I got
Error 438 "Object doesn't support this property or method"
The whole code:
Sub Proceed_Data()
Dim FileSystemObj As Object
Dim FolderObj As Object
Dim fileobj As Object
Dim Sheet_name As Worksheet
Dim i, j, k As Integer
Dim wb As Workbook
Set FileSystemObj = CreateObject("Scripting.FileSystemObject")
Set FolderObj = FileSystemObj.GetFolder("C:\...\")
For Each fileobj In FolderObj.Files
Set wb = Workbooks.Open(fileobj.Path)
Set Output_tot_n = Workbooks("Final_Output").Sheet_name.Range("B7")
If wb.Name = "AAA_SEPT_2018" Then
Sheet_name = Worksheets("AAA")
End If
If wb.Name = "BBB_SEPT_2018" Then
Sheet_name = Worksheets("BBB")
End If
If wb.Name = "CCC_SEPT_2018" Then
Sheet_name = Worksheets("CCC")
End If
' conditional sum
With wb.Sheets("REPORT")
For i = 2 To .Cells(Rows.Count, 14).End(xlUp).Row
If .Cells(i, "O").Value = "sept" Then
k = .Cells(i, "M").Value
End If
j = j + k
k = 0
Next i
End With
Output_tot_n = j
j = 0
wb.Save
wb.Close
Next fileobj
End Sub
Workbooks is a collection (part of the actual Application-object). A collection in VBA can be accessed either by index number (index starts at 1) or by name. The name of an open Workbook is the name including the extension, in your case probably either Final_Output.xlsx or Final_Output.xlsm.
Sheets and Worksheets are collections within a Workbook, again accessed via index or name (the difference is that Worksheets contains "real" spreadsheets while Sheets may also contain other sheet types, eg charts).
So in your case, you want to access a Range of a specific sheet of a specific workbook. The workbook has a fixed name, while the sheet name is stored in a variable. You can write for example
dim sheetName as string, sheet as Worksheet, Output_tot_n as Range
sheetName = "AAA" ' (put your logic here)
set sheet = Workbooks("Final_Output.xlsm").Worksheets(Sheet_name)
set Output_tot_n = sheet.Range("B7")
or put all together (depending on your needs)
set Output_tot_n = Workbooks("Final_Output.xlsm").Worksheets(Sheet_name).Range("B7")
No it actually works. Thank you again for your answers.
the problem was just is important to put "AAA_SEPT_2018.xlsx"

Why does using Rows.Count only find the first 12 rows of data?

I'm trying to find the rows with data in my source data sheet and then copy some of the columns into various places in my destination worksheet using VBA. I have successfully done this for a list with 12k lines but when I do some test data, it only copies the first 12 rows out of 19 rows of data....
Sub Header_Raw()
Dim dataBook As Workbook
Dim Header_Raw As Worksheet, Header As Worksheet
Dim dataSource As Range, dataDest As Range
Dim sourceDataRowCount As Integer, index As Integer
Set dataBook = Application.ThisWorkbook
Set sheetSource = dataBook.Sheets("Header_Raw")
Set sheetDest = dataBook.Sheets("Header")
Set dataSource = sheetSource.Range("B4", _
sheetSource.Range("J90000").End(xlUp))
sourceDataRowCount = dataSource.Rows.Count
Set dataDest = sheetDest.Range("B13", "B" & _
sourceDataRowCount)
For index = 1 To sourceDataRowCount
dataDest(index, 1).Value = dataSource(index, 1).Value
dataDest(index, 2).Value = dataSource(index, 2).Value
Next index
End Sub
If you can help tell me what I have done wrong, that would be great
thanks
Julie
Make your life a bit easier with simple debugging. Run the following:
Sub HeaderRaw()
'Dim all the variables here
Set dataBook = Application.ThisWorkbook
Set SheetSource = dataBook.Sheets("Header_Raw")
Set sheetDest = dataBook.Sheets("Header")
Set dataSource = SheetSource.Range("B4", SheetSource.Range("J90000").End(xlUp))
SheetSource.Activate
dataSource.Select
End Sub
Now you will see what is your dataSource, as far as it is selected. Probably it is not what you expect.

Runtime Error 9 on Loop

I have three workbooks; all with information on the same policies, but come from different documents. I'm trying to copy the value of the same cell from each worksheet that has the same worksheet name in workbooks 1 & workbook 3. This is the code that I have:
Sub foo()
Dim wbk1 As Workbook
Dim wbk2 As Workbook
Dim wkb3 As Workbook
Dim shtName As String
Dim i As Integer
Set wkb1 = Workbooks.Open("C:\Users\lliao\Documents\Trad Reconciliation.xlsx")
Set wkb2 = Workbooks.Open("C:\Users\lliao\Documents\TradReconciliation.xlsx")
Set wkb3 = Workbooks.Open("C:\Users\lliao\Documents\Measure Trad Recon LS.xlsx")
shtName = wkb2.Worksheets(i).Name
For i = 2 To wkb2.Worksheets.Count
wkb2.Sheets(shtName).Range("D3").Value = wkb1.Sheets(shtName).Range("D2")
wkb2.Sheets(shtName).Range("E3").Value = wkb1.Sheets(shtName).Range("E2")
wkb2.Sheets(shtName).Range("F3").Value = wkb1.Sheets(shtName).Range("F2")
wkb2.Sheets(shtName).Range("D4").Value = wkb3.Sheets(shtName).Range("D2")
wkb2.Sheets(shtName).Range("E4").Value = wkb3.Sheets(shtName).Range("E2")
wkb2.Sheets(shtName).Range("F4").Value = wkb3.Sheets(shtName).Range("F2")
Next i
End Sub
I don't understand how I'm using the subscript wrong. This is my first time coding VBA (first time in 5+ years), so I'm unfamiliar with coding errors.
Thank you!
Dim i As Integer
Set wkb1 = Workbooks.Open("C:\Users\lliao\Documents\Trad Reconciliation.xlsx")
Set wkb2 = Workbooks.Open("C:\Users\lliao\Documents\TradReconciliation.xlsx")
Set wkb3 = Workbooks.Open("C:\Users\lliao\Documents\Measure Trad Recon LS.xlsx")
shtName = wkb2.Worksheets(i).Name
Variable i is declared, but used before it's assigned - its value is therefore an implicit 0.
With VBA collections being 1-based, that makes wkb2.Worksheets(i) be out of bounds.
Dim i As Integer
i = 1
'...
shtName = wkb2.Worksheets(i).Name
Will fix it.
You probably want to move it inside the loop though.
may be you're after this:
For i = 2 To wkb2.Worksheets.Count
wkb2.Sheets(i).Range("D3:F3").Value = wkb1.Sheets(i).Range("D2:F2")
wkb2.Sheets(i).Range("D4:F4").Value = wkb3.Sheets(i).Range("D2:F2")
Next i

Object Variable or With Block variable not set

OBJECTIVE
Business units submit monthly financial information to Corporate each month. Develop a VBA macro that will pull in financial data from multiple business units.
APPROACH
Create a MASTER workbook that consolidates each business unit's information. Make sure that each business unit is represented in the MASTER workbook ("Target_workbook") with their own tab (e.g "1120", "1130", "1210"; "businessUnit")
Create an array from each of the business unit tabs ("arr")
Use array information to find corresponding Monthly financial report ("Source_Workbook", "Source_Path")
Copy and paste financial information into the MASTER workbook ("Target_workbook") and corresponding business unit's tab (businessUnit)
CODE
Sub getBusinessUnits()
Dim ws As Worksheet
Dim Target_Workbook As Workbook
Dim Source_Workbook As Workbook
Dim element As Variant
Dim col As New Collection
Dim Source_Path As String
Dim businessUnit As String
Dim businessName As String
'Set up collection to identify Business Unit Tabs and convert into array
For Each ws In ThisWorkbook.Worksheets
If IsNumeric(ws.Name) Then
col.Add ws.Name
Dim arr As Variant
End If
Next
arr = toArray(col) 'Collection converted into Array
'Loop through worksheets in array, open relative workbook, and pull in relevant data
For i = LBound(arr, 1) To UBound(arr, 1)
'assign business unit information to variables.
'Define workbook where we will paste copied information (target_workbook)
businessUnit = ThisWorkbook.Sheets(arr(i)).Activate
Set Target_Workbooks = ThisWorkbook.Sheets(arr(i))
businessName = ActiveSheet.Cells(2, 2)
'Open up the corresponding business unit's financial report, copy data
Source_Path = ThisWorkbook.Path & "\Business Unit Monthly Reporting Template_" & businessName & ".xlsx"
Set Source_Workbook = Workbooks.Open(Source_Path)
Source_Workbook.Sheets("Auth Expense Data Entry").Range("A1:H150").Copy
'Paste copied information from Source_Workbook into Target_workbook
Target_Workbook.Sheets(arr(i)).Range("A5").PasteSpecial Paste:=xlPasteValues '!!!ERROR: "Object Variable or With Block variable not set" !!!!
'Clear cache, close source_workbook
Application.CutCopyMode = False
Source_Workbook.Close (False)
End
Next
End Sub
'Function to convert collection into array
Function toArray(col As Collection)
Dim arr() As Variant
ReDim arr(1 To col.Count) As Variant
For i = 1 To col.Count
arr(i) = col(i)
Next
toArray = arr
End Function
ISSUES
Error # Line: Target_Workbook.Sheets(arr(i)).Range("A5").PasteSpecial Paste:=xlPasteValues, "Object Variable or With Block variable not set". Why is this the case? Is it because the arr(i) is a variant/string?
Any other suggestions for code improvement?
You have Set Target_Workbooks
, remove the s.

Resources