I recently posted a question about how to "group" several open workbooks (not all workbooks). A couple techniques were mentioned, all of which I think I could make work but one technique seemed to stick out at me as being exactly what I needed. Creating a collection and putting the workbooks in the collection. Then I can refer to this collection throughout my program as needed. So... I began reading up on / learning about collections. However, Several articles compared collections to being similar to arrays. Which had me second guessing myself as to which one I should use. I am having trouble understanding if an array can even store "objects"? For example can an array store several "objects"? i.e: store several "workbooks"?
to store workbooks in an array we can create an array of workbooks:
Sub kjkj()
Dim wkbks(1 To 4) As Workbook
Set wkbks(1) = workbooks.Open(....)
Set wkbks(2) = workbooks.Open(....)
Set wkbks(3) = workbooks.Open(....)
Set wkbks(4) = workbooks.Open(....)
Dim i As Long
For i = 1 To 4
With wkbks(i)
'do something
End With
Next i
End Sub
Related
I was wondering if there is a way to keep some values stored in an array after the code ends and the excel file is closed.
The idea would be to have an array containing some values. When running the code, I might or might not modify some of its values and when I close the file I'd like this array to subsist and keep its values.
What I mean by that is that when I would re-open the file and run the code, all the other variables would be re-initialised (and obviously would get default values again), but this special array would still have all its values stored (so I would of course not re-declare it in that code).
One way to avoid this trouble would be to store all the values contained in the array in a worksheet and whenever the code is run again, put them back into a new array.
But I am wondering if there is a way to do this without using a worksheet.
One tends to think of a worksheet as the heart and soul of Excel and is, therefore, reluctant to make "such a big effort" to store just one array. From Excel's point of view a sheet is nothing more than an array, taking up just a few bytes of memory while it is empty. I would argue that a VeryHidden worksheet is precisely what you are asking for, in fact very similar to Word's Document Variables.
As an alternative I could suggest using one of the built-in properties, such as Keywords or Comments, to store a string which can be Split into an array. This would probably be more to your liking but I think it is inferior because the user can edit it, unless that is something you can use to your advantage.
Technically, and for all practical purposes, a VeryHidden worksheet is precisely what you are asking for. Your resistance is based in psychology, not reason - at least, that is how I convinced myself, and I can say being more liberal with the number of worksheets I create has given me more liberties at no perceptible cost.
Either store information, as you mentioned, within a (hidden) sheet, or use Document Variables.
From the documentation:
Sub AddDocumentVariable()
ActiveDocument.Variables.Add Name:="Age", Value:=12
End Sub
These variables will be available even if your code has finished or the workbook was closed and opened again.
Edit: (for excel, code found here)
Sub test()
Dim wb As Workbook
Dim docProps As DocumentProperties
Dim docProp As DocumentProperty
Set wb = ActiveWorkbook
Set docProps = wb.CustomDocumentProperties
With docProps
.Add Name:="CustomNumber", _
LinkToContent:=False, _
Type:=msoPropertyTypeNumber, _
Value:=1000
.Add Name:="CustomString", _
LinkToContent:=False, _
Type:=msoPropertyTypeString, _
Value:="This is a custom property."
.Add Name:="CustomDate", _
LinkToContent:=False, _
Type:=msoPropertyTypeDate, _
Value:=Date
End With
For Each docProp In docProps
Debug.Print docProp.Name, docProp.Value
Next
End Sub
sort of a newbie with VBA and I was wondering how you can create a dynamic 2D array which will be the size of the selected data in excel (Not knowing how big the data is) . I am unfamiliar with the VBA syntax and most of the questions I saw dealt with static data where the person knows the size of the excel table.
I have already created a function which automatically selects the data in the excel sheet. Now I wish to know how I can place all these data into a 2D Array.
Sorry if this is a common question, I am more familiar with 2D arrays with other languages, however I am getting mixed up with people using Range, Array and others in VBA
Also the data is strings in each element of the table. Please also advise how I will pull this data out :) Thank you
This code will put into array for you ..
Sub SelectionToArray()
Dim arrSelection() As String
Dim i As Integer
i = 0
ReDim arrSelection(i)
For Each c In Selection
arrSelection(i) = c.Value
i = i + 1
ReDim Preserve arrSelection(i)
Next c
End Sub
I am creating a Word userform using VBA. I store several configuration using array in the program code, such as the following:
Public arrConfiguration[2, 3] as Integer
where index 2 represent type 0 to 2, and index 3 represent properties 0 to 3 for each type.
However, I planned to modify the program for larger amount of data (such as for 100 different types of data and 50 properties for each data).
My question is,
should I keep storing the data using array in the program, so that it will be
Public arrConfiguration[99, 49] as Integer
or store it in an Excel file, and make the program open the Excel file and access the cells repeatedly? Which one is better?
Thank you.
Please prefer excel. Sample example data image is appended here-under.
For creating two dimensional dynamic array in excel, follow the steps below:
◾Declare the two dimensional Array
◾Resize the array
◾Store values in array
◾Retrieve values from array
Sub FnTwoDimentionDynamic()
Dim arrTwoD()
Dim intRows
Dim intCols
intRows = Sheet1.UsedRange.Rows.Count
intCols = Sheet1.UsedRange.Columns.Count
ReDim Preserve arrTwoD(1 To intRows, 1 To intCols)
For i = 1 To UBound(arrTwoD, 1)
For j = 1 To UBound(arrTwoD, 2)
arrTwoD(i, j) = Sheet1.Cells(i, j)
Next
Next
MsgBox "The value is B5 is " & arrTwoD(5, 2)
End Sub
In the Message Box you will get the following output.
Further To visualize a two dimensional array we could picture a row of CD racks. To make things easier, we can imagine that each CD rack could be for a different artist. Like the CDs, the racks would be identifiable by number. Below we'll define a two dimensional array representing a row of CD racks. The strings inside of the array will represent album titles.
For multidimensional arrays it should be noted that only the last dimension can be resized. That means that given our example above, once we created the array with two CD racks, we would not be able to add more racks, we would only be able to change the number of CDs each rack held.
You can simplify #skkakkar code:
dim x as variant
x = range("A1").CurrentRegion
No Redim, no loops.
Depending on how you see things evolving, you might want to consider accessing your Excel data via ADO, rather than OLE Automation. That way, if you decide to change your storage system to Access, SQL Server or something else, you will have less work to do.
How To Use ADO with Excel Data from Visual Basic or VBA (Microsoft)
https://support.microsoft.com/en-gb/kb/257819
Read and Write Excel Documents Using OLEDB (Codeproject)
http://www.codeproject.com/Tips/705470/Read-and-Write-Excel-Documents-Using-OLEDB
I am new to VBA. I am trying to create a set of code that will allow me to start and stop a loop in between a set of worksheets.
Background: I have a file that I use to update several important factors for financial analysis and certain tabs are grouped together. Since this file is always adding and subtracting tabs, I cant set a loop for a set number of worksheets. I do have a set of tabs that are never moved in between each grouping.
So I would like to create a loop that will start at tab "X+1" and loop until it reaches tab "Y-1", as I dont want the loop to ac. The code inbetween I already have written and worked out, but I'm not very good at looping yet.
Dim i as integer
For i = X+1 to Y-1
Sheets(i).Select
.... your code
Next i
The correct way to loop over several worksheets in the current workbook is:
Dim i As Integer
Dim wrksheet As Worksheet
For i = 1 To Sheets.Count
Set wkrsheet = ThisWorkbook.Sheets(i)
'Do work on wrksheet object
Next i
You can loop on any subset of the Sheets collection by starting on a number greater than 1 or ending on a number less than Sheets.Count, but make sure you don't exceed those bounds.
If you wish to filter out certain sheets, you can skip logic based on sheet names, by checking wrksheet.Name.
Make sure you aren't using logic that involves Sheet.Select or .Activate, this will only lead to trouble down the road. Your code should always operate on Worksheet objects by direct reference rather than relying on state dependent variables like ActiveSheet.
A question on variants. Im aware that variants in Excel vba are both the default data type and also inefficient (from the viewpoint of overuse in large apps). However, I regularly use them for storing data in arrays that have multiple data types. A current project I am working on is essentially a task that requires massive optimistaion of very poor code (c.7000 lines)- and it got me thinking; is there a way around this?
To explain; the code frequently stores data in array variables. So consider a dataset of 10 columns by 10000. The columns are multiple different data types (string, double, integers, dates,etc). Assuming I want to store these in an array, I would usually;
dim myDataSet(10,10000) as variant
But, my knowledge says that this will be really inefficient with the code evaluating each item to determine what data type it is (when in practise I know what Im expecting). Plus, I lose the control that dimensioning individual data types gives me. So, (assuming the first 6 are strings, the next 4 doubles for ease of explaining the point), I could;
dim myDSstrings(6,10000) as string
dim myDSdoubles(4,10000) as double
This gives me back the control and efficiency- but is also a bit clunky (in practise the types are mixed and different- and I end up having an odd number of elements in each one, and end up having to assign them individually in the code- rather than on mass). So, its a case of;
myDSstrings(1,r) = cells(r,1)
myDSdoubles(2,r) = cells(r,2)
myDSstrings(2,r) = cells(r,3)
myDSstrings(3,r) = cells(r,4)
myDSdoubles(3,r) = cells(r,5)
..etc...
Which is a lot more ugly than;
myDataSet(c,r) = cells(r,c)
So- it got me thinking- I must be missing something here. What is the optimal way for storing an array of different data types? Or, assuming there is no way of doing it- what would be best coding-practise for storing an array of mixed data-types?
Never optimize your code without measuring first. You'll might be surprised where the code is the slowest. I use the PerfMon utility from Professional Excel Development, but you can roll your own also.
Reading and writing to and from Excel Ranges is a big time sink. Even though Variants can waste a lot of memory, this
Dim vaRange as Variant
vaRange = Sheet1.Range("A1:E10000").Value
'do something to the array
Sheet1.Range("A1:E10000").Value = vaRange
is generally faster than looping through rows and cells.
My preferred method for using arrays with multiple data types is to not use arrays at all. Rather, I'll use a custom class module and create properties for the elements. That's not necessarily a performance boost, but it makes the code much easier to write and read.
I'm not sure your bottleneck comes from the Variant typing of your array.
By the way, to set values from an array to an Excel range, you should use (in Excel 8 or higher):
Range("A1:B2") = myArray
On previous versions, you should use the following code:
Sub SuperBlastArrayToSheet(TheArray As Variant, TheRange As Range)
With TheRange.Parent.Parent 'the workbook the range is in
.Names.Add Name:="wstempdata", RefersToR1C1:=TheArray
With TheRange
.FormulaArray = "=wstempdata"
.Copy
.PasteSpecial Paste:=xlValues
End With
.Names("wstempdata").Delete
End With
End Sub
from this source that you should read for VBA optimization.
Yet, you should profile your app to see where your bottlenecks are. See this question from Issun to help you benchmark your code.