I would like to be able to reference the next worksheet in a workbook using VBA, but avoid referencing the sheet name as I hope to be able to apply the macro to a number of different workbooks.
I am writing an Excel Macro which is for formatting an excel chart. In the chart's series title I would like to make the series name reference a cell in the next worksheet.
I have tried the following which is not working:
ActiveChart.SeriesCollection(1).Name = "='ActiveChart.Next.Select'!$B$1"
However this is not working.
What is the most effective way of getting the series name field of a chart to reference a cell in the following worksheet within a macro?
I have also tried the following, which does not work either:
ActiveChart.SeriesCollection(1).Name = "=Sheets(1)!$B$1"
Please bear in mind that this is a workbook which is structured with a chart, then a sheet, chart, sheet and so on...
You can use this one-liner
ActiveChart.SeriesCollection(1).Name = "='" & Sheets(ActiveChart.Parent.Parent.Name).Next.Name & "'!B1
Sheets(ActiveChart.Parent.Parent.Name returns the name of the next sheet.
The pair of ' are important to use when referring to sheetnames. i.e. a sheet named My Sheet won't work as My Sheet!B1, it must be 'My Sheet'!B1
Looks like you are trying to put VBA code instead of classical Excel formula reference. I havent ever tried it but I pressume that it wont work. If you want to reference something to a cell you must create the formula in that good old clear syntax with =, sheetname, !, cell address something like:
=Sheet1!A1
You can ofcourse use VBA to create this formula for you and assign it to the field. Try this code:
Dim ws As Worksheet
Dim formula As String
Set ws = ActiveSheet.Next
formula = "=" & ws.name & "!A1"
ActiveChart.SeriesCollection(1).name = formula
Related
This question already has answers here:
Excel VBA Sum from Multiple Sheets
(3 answers)
Closed 3 years ago.
I need to sum values across multiple sheets. The sheets will always have different names as they are set by the date.
I have a summary sheet as the first sheet in my workbook.
From a field in my summary sheet, I'd like to read through each sheet and if the value of the fields match it adds the values together.
For example, pseudo code would be, Go through each worksheet and if SummarySheet.Range("A24").value is in range(G1:G200) sum up the corresponding cell in range("H1:H200").
I've tried sum if and sum product.
I've tried the below code. Which bombed!
For Each Cell In Range("A24:A224")
For Each ws In ThisWorkbook.Worksheets
For Each i In ThisWorkbook.ActiveSheet.Range("G2:H200")
If Cell.Value = i.Value Then
ActiveCell.Offset(0, 1).Select
Cell.Value = Cell.Value + i.Value
End If
Next i
Next ws
Next Cell
Your code is referencing "ActiveSheet" and "ActiveCell" but it's not activating anything within the loop.
It is very difficult to guess what your code is trying to do. This answer is more about good coding practice than specific recommendations. My hope is this will allow you to correct your own code.
ActiveCell.Offset(0, 1).Select serves no purpose. The ActiveCell is the cell containing the cursor. You do not position the cursor at the beginning of the routine to a first cell and you neither read from nor write to the ActiveCell during the rest of the macro.
For Each ws In ThisWorkbook.Worksheets serves no purpose since you do not use ws. In For Each i In ThisWorkbook.ActiveSheet.Range("G2:H200") did you mean to write For Each i In ws.Range("G2:H200")? I cannot see anywhere else you might have meant to use ws.
Each Cell In Range("A24:A224") references the ActiveSheet. This is whatever worksheet happens to be active when the macro was started. My guess is that Range("A24:A224") is in the summary worksheet. If the user happens to be looking at another worksheet when they start the macro, that other worksheet is the ActiveSheet and not the summary worksheet. I assume you want to accumulate totals in the summary worksheet. If the wrong worksheet is active when the macro is started, that worksheet will be corrupted beyond recovery. UnDo cannot undo what a macro has done so you will have to revert to the previous copy of the workbook. I hope you create a new copy of the workbook before trying experimental macros so you can revert to an undamaged version. You need something like:
Dim WshtSumm As Worksheet
Set WshtSumm = Worksheets("Summary")
For Each Cell In WshtSumm.Range("A24:A224")
: : : : : : :
Next
In my opinion, you should not use names like Cell because it is too similar to the reserved word Cells. You should not use names like i because such names are meaningless. Perhaps it does not matter in such a small macro but, as your macros get bigger, meaningful names will be a real help when you or someone else looks at this macro in six or twelve months. Few macros last unchanged for ever; they are updated every few months to address changing requirements. I do not know what Cell and i represent but perhaps CellSumm and CellData would be better names.
Consider ThisWorkbook.Worksheets and Range("A24:A224"). I have just told you that you should have identified which worksheet holds Range("A24:A224"). This was because your workbook holds several worksheets any of which could be active. If you have a workbook that has only one worksheet, Range("A24:A224") might be OK. Personally, I avoid unqualified ranges because it is so easy to add a new worksheet. However, is it likely that you will have two workbooks or more workbooks open? Yes, it is possible to run a macro in one workbook from another workbook but is this likely? ThisWorkbook identifies the workbook holding the macro. If you are concerned that the wrong workbook will be active, you are absolutely correct to specify which collection of worksheets you wish to access because each workbook has its own collection. However, Worksheets on its own will normally be sufficient. This is something you need to think about, particularly as your macros get more complicated: do I need to qualify this range or worksheet or anything of which you might have more than one?
Consider:
For Each ws In ThisWorkbook.Worksheets
For Each i In ws.Range("G2:H200")
I have not qualified ws because a worksheet has a property Parent which identifies its workbook. You qualified ws when you created it.
One of the worksheets in ThisWorkbook.Worksheets will be the summary worksheet. Do you want to examine cells in the summary worksheet? I assume not. You need something like:
Dim WshtSumm As Worksheet
Dim WshtOther As Worksheet
Set WshtSumm = Worksheets("Summary")
For Each WshtOther In Worksheets
If WshtOther.Name <> WshtSumm.Name Then
: : : : : : :
End If
Next
This code only examines worksheets whose name does not match the summary worksheet's name. Whenever you look through an entire collection of something, you need to ask yourself: do I really want to look at everyone?
Consider:
If Cell.Value = i.Value Then
ActiveCell.Offset(0, 1).Select
Cell.Value = Cell.Value + i.Value
End If
Where you have written ActiveCell, I suspect you meant Cell giving:
If Cell.Value = i.Value Then
Cell.Offset(0, 1).Select
Cell.Value = Cell.Value + i.Value
End If
This would make a little more sense but not much. You search Range("G2:H200") of every worksheet for a value that matches a value in Range("A24:A224") of the summary worksheet. If you find that matching value you add it to the next cell in Range("A24:A224"). You tell us nothing about the summary worksheet or the data worksheets so this may be sensible but it does not feel sensible. If you find a match on "A30", you add the value of "A30" to "A31". But then you search for a match on the amended "A31". I cannot imagine any requirement for which this would be sensible.
Even if I thought this was sensible, I don’t think it will work. If I write:
For X = 1 to 10
: :
Next
I cannot change the value of X within the For Loop. I have not tried recently but my recollection is that the attempt to change X is ignored. You are trying to change the equivalent of X for a For Each statement. I have not tried but I suspect your attempt to change Cell will fail. Even if it can change Cell you should not. Select is a slow command and you should only use it if it is essential. Try something like:
If Cell.Value = i.Value Then
Cell.Offset(0, 1).Value = Cell.Offset(0, 1).Value + i.Value
End If
I hope the above helps. If it does not, please provide details of the two ranges so I can better understand what you are trying to do.
I just tried this and it worked perfect.
Sub GenerateTheFormula()
Dim x, Formula
Formula = "=SUM(" 'Formula begins with =SUM(
For x = 3 To Sheets.Count
Formula = Formula & Sheets(x).Name & "!A1," 'Add SheetName and Cell and Comma
Next x
Formula = Left(Formula, Len(Formula) - 1) & ")" 'Remove trailing comma and add parenthesis
Range("B1").Formula = Formula 'Where do you want to put this formula?
End Sub
Idea from here:
Excel VBA Sum from Multiple Sheets
I had this case like
=SUMIF(SBI!C:C,"B",SBI!A:A)
Here SBI is the sheet name which I have hardcoded. I wanted to mention a reference to this Sheet name instead of hardcoding it.
I already have Column in current sheet which has the Sheet names mentioned in a column.
If you're not using VBA then you need an indirect cell reference that will contain a sheet name. E.g. in cell A1 you have the name "SBI", then the formula would be:
=SUMIF(INDIRECT("'"&$A$1&"'!C:C"),"B",INDIRECT("'"&$A$1&"'!A:A"))
If you're using VBA then in the code you simply need a Worksheet variable and can use its Range properties or just concatenate a string:
Dim WS as Worksheet
Set WS = Thisworkbook.Worksheets("SBI")
Range("A:A").Formula = ("=SUMIF('" & WS.Name & "'!C:C,""B"",'" & WS.Name & "'!A:A)")
The reason I'm putting ' quote marks around any sheet name is in case a sheet name has a space in it E.g. Sheet2!A:A will work but Sheet 2!A:A will not... you should always put worksheet names in quotes for safety and future-proofing :D 'Sheet 2'!A:A
Can someone help me with the implementation of this?
Range("B3").Formula = "=SUMIF(Active.Select!$A:$A,Results.select!$A3,Active.select!B:B)"
I have defined Active and Results as WorkSheet and my objective was to have a dynamic reference to them so so that the macro cna be run on any sheet of the workbook without having any kind of static referece lik Sheet1!
If i try to run what i have wrote he ask me to provide Active and Results through a open... window
I know it might be a noobish question but i am just getting started
If you remove the sheet names then the formula will refer to the Worksheet that it is on.
Range("D2").Formula = "=SUMIF($A:$A,$E$1,$B:$B)"
Worksheets have an Evaluate method that will return the value of a formula
Note: I didn't use Range("B3").Formula = "=SUMIF($A:$A,$A3,B:B)" because it is a circular reference.
Assuming that Active and Results are both Worksheet objects, then if you wish to create a formula to go into cell B3 of the ActiveSheet, try this:
Range("B3").Formula = "=SUMIF('" & Active.Name & "'!$A:$A,'" & Results.Name & "'!$A3,'" & Active.Name & "'!B:B)"
If you want to just obtain the value and use it for something within VBA, try this:
Dim sumIfResult As Double
sumIfResult = Application.WorksheetFunction.SumIf(Active.Range("$A:$A"),Results.Range("$A3"),Active.Range("B:B"))
I have a problem with a VBA script. I guess the solution is simple, but I just wasnt able to figure it out....
So basically, I have a workbook that contains many worksheets. Each worksheet contains the exact same format of a table (same number of rows and columns). What I wanted to do was to create a new worksheet and in that worksheet, have averages of all those values.
So for example in cell B2 I want to have average of cells B2 from all the other worksheets. I therefore created a macro that does this, this is not a problem, the problem is however, that in that macro, all sheets are referred to by their names and since I have many of these workbooks with differently named sheets, this would not work. I therefore tried to change the name of the first sheet to actual reference of sheet - i.e. Sheet(1) and the last one as Sheet(x) - where x is the number of sheets I calculated previously. Unfortunately the code doesnt work, could anyone please suggest to me how to modify this so that it works properly? I am only copying the problematic part of the code:
x = Sheets.Count
Sheets.Add After:=Sheets(x)
Range("B2").Select
ActiveCell.FormulaR1C1 = "=AVERAGE(Sheets(1):Sheets(x)!RC)"
Try this. You are not offseting your sheet names (in fact, you're not even using the sheet names. In the context of a formula, Sheets(1) is meaningless. You need to use Sheets(1).Name and offset it appropriately:
"=AVERAGE('" & Sheets(1).Name & ":" & Sheets(x).Name & "'!RC)"
I'm trying to make a macro that seems pretty simple, but it's proven to be harder than I thought. I started making it using the "point and click" method, but it hasn't been as dynamic as I had thought. Basically I'm using vlookup to look up the names in cell A2 from another worksheet, then copy numbers in column D over to the current sheet. When looking at the code, it looks something like this for this part:
Range("D2").Select
ActiveCell.FormulaR1C1 = _
"=VLOOKUP(RC[-3],'Downstairs'!R[-1]C[-3]:R[200]C[14],4,0)"
Range("D2").Select
Selection.AutoFill Destination:=Range("D2:D" & lastrow&)
After I find the first number, I'm trying to autofill the rest. It works when you run it but I think it's just because the names are in order. However, if the names aren't in order it won't find the correct number, partly because all the numbers inside the R[] and C[] keep changing as you go down the rows. I don't think it will work if I add more names to the list, which is something I need for it to do. I changed the number inside the R[] from 93 to 200 because I don't really know how to incorporate the lastrow object I had made before, and I don't know of another way to make this dynamic. Is there a better way to do this?
Like I mentioned in my comment above, you do not need VBA for this. You can directly type the formula in Excel and do a manual Autofill. Having said that if you still want to do VBA then simply use this code where you do not need to use AutoFill. This code will fill all the relevant cells with formulas.
Your formula was also not giving you the right results as your table array was not constant and it was changing as you moved down. To prevent that from happening, simply use $ sign.
Another Tip: R1C1 format is very confusing if you are not good with it. Stick to the normal A1 formatting.
Here is the most simple way to achieve what you want. Please amend the code to suit your needs
Sub Sample()
Dim ws1 As Worksheet, ws2 As Worksheet
Dim lastrow As Long
'~~> Change this to the releavnt sheet name
'~~> This is the sheet where the formula will go
Set ws1 = ThisWorkbook.Sheets("Sheet1")
Set ws2 = ThisWorkbook.Sheets("Downstairs")
With ws1
'~~> Get the last row
lastrow = .Range("A" & .Rows.Count).End(xlUp).Row
'~~> Fill formula in all the relevant cells in one go
'~~> replace my formula within quotes with your formula
'~~> Do not forget to put the $ sign like I have done
.Range("D1:D" & lastrow).Formula = "=VLOOKUP(A1,Downstairs!$C$1:$N$200,4,0)"
End With
End Sub