So i have an excel file where i can enter the different projects that i want to analyse and the location of the files. Then a code to go and get the files and generate 2 sheets (from a template that i created) for each project entered and populate the data. These projects can vary the name and quantity.
My problem appears when i try to do a total table. Where i would go and get from the same cell in the different sheets the value and sum them. The number of sheets can change so i didnt manage to use a sheets.count, but the name of the sheets that relevant for this operation all start by "Total_".
So the beginning of the code that i have so far is:
`Sub refresh()
Parametre
Dim nbOnglet As Integer
Dim nbProjet As Integer
Dim name As String
Dim nametot As String
Dim A As String
Dim B As String
Dim idx As Integer
Dim iDebut As Integer
Dim values As Variant
Dim rng As Range
Dim xRng As Range
Dim x As Long
Dim vArray As Variant
Dim dSum As Double
Initialisation
iDebut = 9
Déterminer le nombre d'onglets du Classeur
nbOnglet = Sheets.Count
Déterminer le nombre de projet à traiter
folderpath = Range("C3").Value
Sheets("Sommaire").Select
nbLigne = Cells(10, "A").Value
x = 0
For idx = 1 To nbLigne
activate Récapitulatif
Sheets("Récapitulatif").Select
Define the variable name - tab name
A = "Total_"
B = Sheets("Sommaire").Cells(iDebut + idx, "D").Value
name = B
nametot = A & B`
Then for the sun i have tried different options but none appears to work for the entire table. I managed to get the good result for one cell by using the following:
x = x + sheets(nametot).range("F7").Value2
But couldn't do it for all the range (F7:CI31).
Other formula that i have tried was:
Set xRng = ThisWorkbook.Sheets(nbLigne).Range("K7:CI31")
xRng.FormulaR1C1 = "=SUM('" & ThisWorkbook.Sheets(nametot).name & "'!RC+'" & ThisWorkbook.Sheets(nametot).name & "'!RC)"
Although this gives the equation that i want since it is running in a loop, it calculates the same for each sheet and stops at the last one identified... So not doing what i would like to: sum the same cell across the different sheets named 'Total_XXXX' and present the value in the 'Récapitulatif' sheet.
I have been looking around internet and i can't really figure out a way to do it.
DO you have any ideas?
Thank you so much in advance
example of the table
Consolidate Worksheets
Links (Microsoft Docs)
Range.Address
Range.Consolidate
XlConsolidationFunction Enumeration
Description
In the workbook containing this code (ThisWorkbook), the following will consolidate (in this case sum up (xlSum)) all the same ranges (srcRange) in all worksheets with names starting with a specified string (srcLead) into another worksheet (tgtName) starting from a specified cell (tgtFirst).
The Code
Option Explicit
Sub consolidateWorksheets()
' Define constants.
Const srcRange As String = "K7:CI31"
Const srcLead As String = "Total_"
Const tgtName As String = "Récapitulatif"
Const tgtFirst As String = "A1"
' Define workbook.
Dim wb As Workbook
Set wb = ThisWorkbook
' Define Target Worksheet.
Dim tgt As Worksheet
Set tgt = wb.Worksheets(tgtName)
' Define R1C1-Style Source Ranges Address.
Dim rcRng As String
rcRng = tgt.Range(srcRange).Address(ReferenceStyle:=xlR1C1)
' Define Consolidation Array.
Dim Data As Variant
ReDim Data(1 To wb.Worksheets.Count)
' Declare variables.
Dim ws As Worksheet ' Current Source Worksheet
Dim CurrentName As String ' Current Source Worksheet Name
Dim n As Long ' Current Element in Consolidation Array
' Write full paths of Source Worksheets to Consolidation Array.
For Each ws In wb.Worksheets
CurrentName = ws.Name
If InStr(1, CurrentName, srcLead, vbTextCompare) = 1 Then
n = n + 1
Data(n) = "'" & ws.Name & "'!" & rcRng
End If
Next ws
' Validate and resize Consolidation Array.
If n = 0 Then
MsgBox "No worksheets to consolidate.", vbCritical, "Fail"
Exit Sub
End If
ReDim Preserve Data(1 To n)
' Consolidate.
tgt.Range(tgtFirst).Consolidate Sources:=Data, _
Function:=xlSum
' Inform user.
MsgBox "Data consolidated.", vbInformation, "Success"
End Sub
Related
I have two excels Book1.xlsm and Book2.xlsx. Book1 will have certain values like alpha, beta, gamma etc. (no repetition) in column A. And Book2 will have multiple occurrence of Book1 values like beta, beta, beta, alpha, alpha, gamma, gamma, gamma, gamma, gamma etc. The values in Book2 may not be alphabetically sorted but same values will be grouped together. Book2 values will be also in column A.
I have a macro designed in Book1.xlsm that should iterate over each value in Book1 column A and find the first row id where same value is present in Book2 column A. This row id should be then copied in corresponding column B of Book1.
This is how my macro code looks like. When I run, it fails with Run Time error '1004': Application-defined or object-defined error
Option Explicit
Sub Get_Data()
Dim wb1 As Worksheet
Dim wb2 As Worksheet
Dim wb2row As Integer
Dim i As Integer
Dim j As Integer
Const A = "A"
Const B = "B"
Set wb1 = Workbooks("Book1.xlsm").Worksheets("Sheet1")
Set wb2 = Workbooks("Book2.xlsx").Worksheets("Sheet1")
'Both For loop start from row id 2.
For i = 2 To wb1.Range("A2", wb1.Range("A2").End(xlDown)).Rows.Count
For j = 2 To wb2.Range("A2", wb2.Range("A2").End(xlDown)).Rows.Count
wb2row = Application.WorksheetFunction.Match(wb1.Cells(i, A), Range(wb2.Cells(j, A)), 0)
wb1.Cells(i, B).Copy (wb2.Cells(j, A))
Exit For ' j loop
Next j
Next i
End Sub
You can make excel do the work for you. Try this (tested)
Sub Get_Data()
With Workbooks("Book1.xlsm").Sheets("Sheet1")
With .Range(.Range("B2"), .Range("A" & Rows.Count).End(xlUp).Offset(0, 1))
.Formula2 = "=IFERROR(MATCH(A2,[Book2.xlsx]Sheet1!$A:$A,0),"""")"
.Value2 = .Value2
End With
End With
End Sub
Match Criteria, Return Row
Option Explicit
Sub Get_Data()
' Source
Const srcFirst As Long = 2
Const srcCol As String = "A"
' Destination
Const dstFirst As Long = 2
Const dstCol As String = "A"
Const resCol As String = "B"
' Source
Dim src As Worksheet
Set src = Workbooks("Book2.xlsx").Worksheets("Sheet1")
Dim rng As Range
Set rng = src.Range(src.Cells(srcFirst, srcCol), _
src.Cells(src.Rows.Count, srcCol).End(xlUp))
Dim RowOffset As Long
RowOffset = srcFirst - 1
' Destination
' 'ThisWorkbook' - the workbook containing this code.
Dim dst As Worksheet
Set dst = ThisWorkbook.Worksheets("Sheet1")
Dim srcRow As Variant ' It could be an error value, hence 'Variant'.
Dim i As Long
For i = 2 To dst.Cells(dst.Rows.Count, dstCol).End(xlUp).Row
srcRow = Application.Match(dst.Cells(i, dstCol), rng, 0)
If Not IsError(srcRow) Then
' This will write the row.
' If you need index, then remove 'RowOffset'.
dst.Cells(i, resCol).Value = srcRow + RowOffset
Else
' no match found, e.g.:
'dst.Cells(i, resCol).Value = ""
End If
Next i
End Sub
The second parameter of match function must be a range not a single cell.
I'm trying to create a macro in excel that takes cell values from one tab and creates a reference to these values as worksheets in vba.
An example of a worksheet list would be the following (could be longer or shorter in length):
sheet1
sheet2
sheet3
...
I have been able to store this in an array using the code below. With this array I would like to take these stored values and use them to reference worksheets as could be done manually as in the following.
ws1= wb.Sheets("sheet1")
ws(i)= wb.Sheets("ws(i)")
Any help to solve this or recommending a different approach would be greatly appreciated!
Thanks, M
Dim wb As Workbook: Set wb = ThisWorkbook
Dim wsInputsList As Worksheet
Set wsInputsList = wb.Sheets("InputsTab")
Dim lastrowInputs As Long
lastrowInputs = wsInputsList.Cells(Rows.Count, 1).End(xlUp).Row
Dim i As Integer
i = 1
Do While i < lastrowInputs
Dim ws(1 To 50) As Variant
ws(i) = wsInputsList.Cells(i + 1, 1).Value
i = i + 1
Loop
Tim Williams gave you the answer
Here I give you some more suggestions
code 1
Option Explicit
Sub SetSheetList()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim wsInputsList As Worksheet: Set wsInputsList = wb.Sheets("InputsTab")
Dim lastrowInputs As Long, i As Long
lastrowInputs = wsInputsList.Cells(Rows.Count, 1).End(xlUp).Row
ReDim ws(1 To lastrowInputs) As Worksheet 'dim your array only once
For i = 1 To lastrowInputs
Set ws(i) = wb.Sheets(wsInputsList.Cells(i, 1).Value)
Next
End Sub
where
moved array dimming outside the loop so as not to dim it lastrowInputs times…
used a For … Next loop which fist more your case (does what you need, does it clearly and in less stataments)
but this kind of sheets listing is prone to some drawbacks, like having a name in the list that is no more actual. For which case you could consider
Code 2
Option Explicit
Sub SetSheetList2()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim wsInputsList As Worksheet: Set wsInputsList = wb.Sheets("InputsTab")
Dim shtName As String
Dim lastrowInputs As Long, i As Long, nshts As Long
lastrowInputs = wsInputsList.Cells(Rows.Count, 1).End(xlUp).Row
ReDim ws(1 To lastrowInputs) As Worksheet 'dim your array only once
For i = 1 To lastrowInputs
shtName = wsInputsList.Cells(i, 1).Value ' store current "possible" sheet name
If IsSheetThere(wb, shtName) Then ' if current "possible" sheet name is an "actual" one
nshts = nshts + 1 ' update sheet names found
Set ws(nshts) = wb.Sheets(shtName) ' update sheets array
End If
Next
If nshts < lastrowInputs Then ReDim Preserve ws(1 To nshts) As Worksheet 'redim your array to the actual number of items stored, if needed
End Sub
And yet ther's a chance your sheet names list in "InputsTab" isn't exhaustive…
As you see, keeping and using such a list can be much more difficult than it might seem at the beginning: it's a matter of focusing on what you really need and why
I'm trying sort a predetermined range of cells from a UserForm (let's say A1:A5) using an array size as an integer, and the array itself. I've checked out 20+ links without finding a solution.
The code below successfully gets the values of the array (for my testing there are five doubles), pastes them into the worksheet sheetOperations (I always use code-targeted sheets to minimize issues). So the sheet targeting works, and the looping through the array and getting the values works.
Sorting the range (A1:A5) hasn't been successful. I've tried a variety of code. I'm trying to get A1 to A5 (on that specific worksheet) to list the previous values in the range in descending order - when I run this code (I tried ascending, descending) it has given me various errors such 1004, etc.
If A1:A5 is {1,3,2, 4, 6}, I want it to make A1:A5 {6,4,2,3,1}.
Sub timeStampStorePart2(ByRef doubleArray() As Double, ByVal size As Integer)
Dim ws As Worksheet
Dim wsFound2 As Worksheet
For Each ws In ThisWorkbook.Worksheets
If StrComp(ws.CodeName, "sheetOperations", vbTextCompare) = 0 Then
Set wsFound2 = ws
'MsgBox ("Found")
End If
Next ws
Dim loopInt As Integer
Dim arrayInt As Integer
Dim rangeAddress As String
arrayInt = 0
loopInt = 1
For loopInt = 1 To size
rangeAddress = "A" & loopInt
wsFound2.Range(rangeAddress).Value = doubleArray(arrayInt)
arrayInt = arrayInt + 1
Next loopInt
'rangeAddress = "A1:" & rangeAddress
'MsgBox (rangeAddress)
'Dim dataRange As Range
'Set dataRange = wsFound2.Range(rangeAddress)
wsFound2.Range("A1:A5").Sort key1:=Range("A2"), order1:=xlAscending, Header:=xlNo
End Sub
In answer to your question, here is a pretty simple code that sorts the range you describe using an array...
slightly updated to meet the integer requirement.
Sub sortStuff()
Const addr As String = "A1:A6"
Dim WS As Worksheet: Set WS = ActiveSheet 'or whatever the sheet ID name is
Dim sRNG As Range: Set sRNG = WS.Range(addr)
'changed this from first answer to integer requirement and optimize code
ReDim aRay(1 To sRNG.Rows.Count, 1 To sRNG.Columns.Count) As Integer
Dim x As Long, y As Long
For x = LBound(aRay, 1) To UBound(aRay, 1)
For y = LBound(aRay, 2) To UBound(aRay, 2)
aRay(x, y) = Application.WorksheetFunction.Large(sRNG.Columns(y), x)
Next y
Next x
'Puts into excel
sRNG = aRay
End Sub
I have to print multiple sheets in excel based on whether that sheet is relevant to a user or not. In a sheet called "Sheet2" I have in column A from cell 14, the sheet names. There are 24 sheets with different names in Column A. In each adjacent cell (in Column B), I have either True or False. I wish to print the sheets which have a True in column B. I am able to print to the sheets one by one and not all the relevant sheets simultaneously as one file. The code I use is as follows:
Sub CommandButton1_Click()
Dim wb As Workbook
Dim SheetsToPrint As String
Set wb = ThisWorkbook
Dim sheetWithData As Worksheet
Set sheetWithData = wb.Sheets("Sheet2")
Dim startNameRange, endNameRange As Integer
startNameRange = 14
endNameRange = 39
For i = startNameRange To endNameRange Step 1
Dim nameSheetToPrint As String
SheetsToPrint = sheetWithData.Range("A" & i).Value
Dim wsToPrint As Worksheet
Set wsToPrint = wb.Sheets(SheetsToPrint)
If sheetWithData.Cells(i, 2) = "True" Then
wsToPrint.PrintOut From:=1, To:=1
End If
Next i
End Sub
Adapt the vars and try this :
Sub PrintSheet()
Dim wb As Workbook
Set wb = ThisWorkbook
Dim sheetWithData As Worksheet
Set sheetWithData = wb.Sheets("Sheet2")
'Add the first row number and the last row number where start the sheet name
Dim startNameRange, endNameRange As Integer
startNameRange = 2
endNameRange = 4
For i = 2 To 4 Step 1
Dim nameSheetToPrint As String
nameSheetToPrint = sheetWithData.Range("A" & i).Value
Dim wsToPrint As Worksheet
Set wsToPrint = wb.Sheets(nameSheetToPrint)
If sheetWithData.Cells(i, 2) = "True" Then
wsToPrint.PrintOut
End If
Next i
End Sub
I know this topic has been asked about before but nothing quite covers what I need. So here's the thing..
I have two workbooks. One is exported from another program which shows a staff member's Surname, first name, email and which ward they work on.
[Workbook1 example]
The second is the full staff list which has the same details but also a check list column.
[Workbook2 example]
What I need is a macro (probably a vlookup) which takes the information from the workbook1, checks against surname, first name and ward on workbook2 to ensure that it is the correct member of staff, copies the email onto workbook 2 and also fills the checklist column on workbook 2 to "Yes".
I'm afraid I am at a loss as to how to incorporate all of this together. Please help.
This is what I have so far but my knowledge is limited and did not know how to proceed.
Private Sub UpdateTraining_Click()
Dim I As Integer
Dim Ws1 As Worksheet
Dim Ws2 As Worksheet
Dim Ws3 As Worksheet
Dim Wb As Workbook
Dim CopyData As String
Dim RwCnt As Long
Dim RwCnt2 As Long
Dim Rw As Long
Dim Clm As Long
Dim SName As String
Dim FName As String
Dim Wrd As String
Dim vArr
Dim ClmLet As String
Set Ws1 = Workbooks("Nursing Docs Training Record.xlsm").Worksheets("Staff Training Record")
Set Ws2 = Workbooks("Nursing Docs Training Record.xlsm").Worksheets("Do Not Use")
Workbooks.Open ("C:\TypeformNursingDocumentation.xlsx")
Set Ws3 = Workbooks("TypeformNursingDocumentation.xlsx").Worksheets("tWeXNp")
RwCnt = Ws3.Cells(Rows.Count, 1).End(xlUp).Row
RwCnt2 = Ws1.Cells(Rows.Count, 1).End(xlUp).Row
Rw = Ws3.Range("F2").Row
Clm = Ws3.Range("F2").Column
Table1 = Ws3.Range("F2:F" & RwCnt)
vArr = Split(Cells(1, Clm).Address(True, False), "$")
ClmLet = vArr(0)
For Each cl In Table1
Ws3.Range(ClmLet & Rw).Select
SName = ActiveCell.Value
FName = ActiveCell.Offset(0, -1).Value
Wrd = ActiveCell.Offset(0, -4).Value
Rw = Rw + 1
Next cl
End Sub
You can achieve this with formulas but then you have to open Workbook1 for the formulas to work in Workbook2. So below approach uses VBA to achieve the results
Copy the below UDF in a module in Workbook2:
Sub UpdateMyList()
Dim oSourceWB As Workbook
Dim oSourceR As Variant
Dim iTotSRows&, iTotCRows&, iCC&, iSC&
Dim oCurR As Variant
Application.ScreenUpdating = False
' First lets get source data
Set oSourceWB = Workbooks.Open("C:\Temp\EmpLookup.xlsx", ReadOnly:=True) ' Change the source file name
With oSourceWB.Worksheets("Sheet1") ' Change the source sheet name
iTotSRows = .Range("A" & .Rows.count).End(xlUp).Row
oSourceR = .Range("A2:G" & iTotSRows)
End With
oSourceWB.Close False
' We now need the data from the sheet in this workbook to compare against
With ThisWorkbook.Worksheets("Sheet8") ' Change the sheet name to the sheet in your workbook
iTotCRows = .Range("A" & .Rows.count).End(xlUp).Row
oCurR = .Range("A2:H" & iTotCRows)
End With
' Next, lets compare and update fields
For iCC = 1 To UBound(oCurR)
For iSC = 1 To UBound(oSourceR)
If (oCurR(iCC, 1) = oSourceR(iSC, 6)) And (oCurR(iCC, 2) = oSourceR(iSC, 5)) And (oCurR(iCC, 5) = oSourceR(iSC, 2)) Then
oCurR(iCC, 7) = oSourceR(iSC, 7)
oCurR(iCC, 8) = "Yes"
Exit For
End If
Next
Next
Application.ScreenUpdating = True
' Finally, lets update the sheet
ThisWorkbook.Worksheets("Sheet8").Range("A2:H" & iTotCRows) = oCurR
End Sub
I've commented on the lines where you need to change references to workbook or worksheets. As long as you have updated the workbook and worksheet references, this should give you the desired results
I built the above UDF based on the columns as you provided in your question. If the columns change, you will have to modify the UDF or get the columns dynamically
You can use and If(Countif()) style function, where the countif checks for the presence of your value, and the if will return true if it is a match, then you can use the if true / false values accordingly. Let me know if you need more details but it could look something like this =IF(COUNTIF(The selected cell is in the selected range),"Yes", "No"). Then record this as a macro and copy the code into yours.