VBA extend range of chart by a variable stored in a cell - vba

This is proper basic but I'm struggling here. I need the range of rows of a data source in a graph to extend or retract by a value I have in "J5". "J5" changes dynamically and I can use a call function for it to work in the graph. Because of the way the charts are set up it has to be this way. My code so far is:
Sub Updatecodelengh()
Dim i As Integer
Dim G As Worksheet
Set G = Sheet1
i = G.Range("J5")
ActiveSheet.ChartObjects("GanttChart").Activate
ActiveChart.SeriesCollection(16).Values = "='Gantt'!$L$3:$L$4"
End Sub
Where it says "='Gantt'!$L$3:$L$4" I need the range of the chart data to start on $L$3 and extend downwards by the value obtained in J5. Thanks for any help

Do you mean simply
ActiveChart.SeriesCollection(16).Values = "='Gantt'!$L$3:$L$" & i
However, you should check if J5 contains a valid number to prevent runtime errors.
A small hint: When dealing with row and column numbers in VBA, always use datatype long.

Related

Iterated EMA formula VBA

I am working on VBA macro, manipulating data on an excel sheet. I have closes of stocks and need to make a collection of EMA (exponential moving average) series. I need to iterate the same couple of formulas over 100 times, but respective to the cells. For example, the first iteration will be =AVERAGE(D153:D164) , then immediately beneath that will be =(2/13)*D165+(11/13)*E164, which will be format copied down (I'll do that). I need to perform these calculations every 70 rows, ending with =AVERAGE(D8973:D8984) & (2/13)*D8985+(11/13)*E8984. Can someone help me derive a functioning macro? Your help is sincerely appreciated.
EDIT: To be more specific, I need to pass the row number as a variable to use in the formulas. If I see how to do so with one variable, I can use that as a foundation. The above 2 formulae are models, yet each instance of each formula will be unique.
Again, thank You.
Assuming the first formulas are the same, and you are always incrementing the same number of rows (70), this code should work. You can change some of my initial assumptions such as the starting cell, number of iterations, etc.
Sub EMAmakeAFunction()
'''''These can be changed as you need
Dim numberOrRowsToSkip As Integer: numberOFRowsToSkip = 70
Dim TrialsToExecute As Integer: TrialsToExecute = 1000
Dim firstFormula As Range: Set firstFormula = Range("D165")
Dim secondFormula As Range: Set secondFormula = Range("D166")
''''Rest of code should be pretty stable of above assumptions are correct.
Dim i As Integer
For i = 1 To TrialsToExecute
firstFormula.Offset(i * numberOFRowsToSkip).FormulaR1C1 = _
firstFormula.FormulaR1C1
secondFormula.Offset(i * numberOFRowsToSkip).FormulaR1C1 = _
secondFormula.FormulaR1C1
Next i
End Sub

Excel VBA: Create a stacked column chart with named table

I'm trying to use VBA to create a stacked column graph using 3 columns of data out of a large ~30 column named table in excel. The desired outcome would be a stacked column graph, where the columns are based on the column "Program" (there are 5 distinct values across ~200 rows) and the numbers that make up the columns are the "SAVINGS - USE THIS" with the corresponding "Project Number"s as those chunks labels. Each row is a distinct project.
For instance, if I have 5 projects in "Program 1," I would want the "SAVINGS - USE THIS" values stacked on top of each other and when a run my mouse over the portions of the column the Project Number would show.
I am fairly new to VBA and am currently editing my previous code to make the project numbers and their savings into a pie graph (originally I didn't care about the program), so if there is a better way to do any of this please let me know.
Sub CreateChart()
Dim labelRng As Range
Dim dataRng As Range
Dim progRng As Range
Dim chtRng As Range
Dim cht As Object
Dim mySeries As Series
Dim vntValues As Variant
Dim i As Integer
Set chtRng = Union(Sheets("CMF").ListObjects("CMF").ListColumns("Program").Range, _
Sheets("CMF").ListObjects("CMF").ListColumns("Project Number").Range, _
Sheets("CMF").ListObjects("CMF").ListColumns("SAVINGS - USE THIS").Range)
'Set progRng = Sheets("CMF").ListObjects("CMF").ListColumns("Program").Range
'Set labelRng = Sheets("CMF").ListObjects("CMF").ListColumns("Project Number").Range
'Set dataRng = Sheets("CMF").ListObjects("CMF").ListColumns("SAVINGS - USE THIS").Range
'Set chtRng = Union(progRng, dataRng, labelRng) 'Sets range for pie
Set cht = Sheets("CMF").Shapes.AddChart2 'Creates chart
For j = cht.Chart.SeriesCollection.Count To 1 Step -1 'Had to be added to avoid errors
cht.Chart.SeriesCollection(j).Delete
Next j
cht.Chart.SetSourceData chtRng 'Sets data range for chart
cht.Chart.ChartType = xlColumnStacked
If this is the best way to do this, my current issue is defining the data range for the graph. You can see I am trying a couple different things, but the problem I'm having is that instead of pulling the "Program" column it is pulling the column that is next to it.
For reference, Project Number is in Column A, Program is in Column C and SAVINGS is in column X. It is pulling Columns A, B and X. Even if I specify the column number as "3" or pull them in a different order, I always have the same issue. The only way I don't have the issue is if I stop pulling in the Project Number and just pull in Program and Savings, which it gets right.
What am I doing that is causing it to pull back the wrong column of data, and once I get the right data in how can I make the stacked columns be organized by Program?
Thanks for reading all of that!
Since you are just assigning SetSourceData at the end, excel is going to do what it thinks is best...which isn't what you want in this case.
Try creating the different Series one at a time and assigning the ranges for each individually after you delete them. Just use the Macro Recorder to go over all the steps that you need to do to create the chart from scratch.

Excel VBA: Insheet function code can not access other cells on sheet

I'm having some issues with an insheet function that I am writing in VBA for Excel. What I eventually am trying to achieve is an excel function which is called from within a cell on your worksheet, that outputs a range of data points underneath the cell from which it is called (like the excel function =BDP() of financial data provider Bloomberg). I cannot specify the output range beforehand because I don't know how many data points it is going to output.
The issue seems to be that excel does not allow you to edit cells on a sheet from within a function, apart from the cell from which the function is called.
I have created a simple program to isolate the problem, for the sake of this question.
The following function, when called from within an excel sheet via =test(10), should produce a list of integers from 1 to 10 underneath the cell from which it is called.
Function test(number As Integer)
For i = 1 To number
Application.Caller.Offset(i, 0) = i
Next i
End Function
The code is very simple, yet nothing happens on the worksheet from which this formula is called (except a #Value error sometimes). I have tried several other specifications of the code, like for instance:
Function test(number As Integer)
Dim tempRange As Range
Set tempRange = Worksheets("Sheet1").Range(Application.Caller.Address)
For i = 1 To number
tempRange.Offset(i, 0) = i
Next i
End Function
Strangely enough, in this last piece of code, the command "debug.print tempRange.address" does print out the address from which the function is called.
The problem seems to be updating values on the worksheet from within an insheet function. Could anybody please give some guidance as to whether it is possible to achieve this via a different method?
Thanks a lot, J
User defined functions are only allowed to alter the values of the cells they are entered into, because Excel's calculation method is built on that assumption.
Methods of bypassing this limitation usually involve scary things like caching the results and locations you want to change and then rewriting them in an after calculate event, whilst taking care of any possible circularity or infinite loops.
The simplest solution is to enter a multi-cell array formula into more cells than you will ever need.
But if you really need to do this I would recommend looking at Govert's Excel DNA which has some array resizer function.
Resizing Excel UDF results
Consider:
Public Function test(number As Integer)
Dim i As Long, ary()
ReDim ary(1 To number, 1 To 1)
For i = 1 To number
ary(i, 1) = i
Next i
test = ary
End Function
Select a block of cells (in this case from C1 through C10), and array enter:
=test(10)
Array formulas must be entered with Ctrl + Shift + Enter rather than just the Enter key.

User Inserted Rows/Columns Impacting Excel VBA

I am trying to determine how I can have a user insert columns and/or rows without it impacting the rest of the code in the macro.
Defining names for my objects and using r1c1 references in VBA does not seem to help as these inserted columns shift those references and names as well.
Am I missing something that should be completely obvious???
Or is what I am trying to accomplish not possible?
UPDATE: When I name a range in excel (without VBA) everything seems to work fine with inserted columns. However, when I name the range with VBA everything messes up. Here is a sample of some code to work with.
When this below code is run... I am not able to insert columns as my MSGBOX's don't realize the named cell has shifted to the right. HOWEVER, if I were to remove the first line in this code and just name the cell "GanttStartLocation" which is quoted out in the code... this seems to work fine.
WHY DOES THiS NOT WORK WHEN NAMED WITH VBA????
ActiveWorkbook.Names.Add Name:="DEFINENAMETEST", RefersToR1C1:="=Sheet1!R10C14"
Dim rGanttLocation As Range 'Range used to define where the Gantt chart begins
Dim iFirstRowGantt As Integer 'Defines the first row of the Gantt chart based on rGanttLocation
Dim iFirstColumnGantt As Integer 'Defines the first column of the Gantt chart based on rGanttLocation
'Set rGanttLocation = Worksheets(1).Range("GanttStartLocation")
Set rGanttLocation = Worksheets(1).Range("DEFINENAMETEST")
iFirstRowGantt = rGanttLocation.Row
iFirstColumnGantt = rGanttLocation.Column
MsgBox (iFirstRowGantt)
MsgBox (iFirstColumnGantt)
Use a named range for your cells so that addition of rows/columns are less likely to impact your code if rows/columns are added inside the range. For example: if D1-F10 was called testrange, executing the following subroutine will give red background color to the range
Public Sub Test()
Range("testrange").Interior.Color = vbRed
End Sub
If a new row and column are added to this range, and the subroutine is re-executed after replacing vbRed with vbYellow, the entire range (with new column and row) will turn yellow.
Outside of the named range, it's going to take decent amount of work to keep your Macro's generic, from what I understand.

Excel VBA for hiding cells in one sheet if they match cells in another sheet

I am new to VBA and am having problems learning the rules of variables (I think that's the problem here).
I have two worksheets in a spreadsheet. I need to make code that automatically hides a row on worksheet 2 if that same value in column a is on worksheet 1, column a.
Here's one of the variations of code I've tried:
Dim Sheet2Value As Variant
Dim Sheet1Value As Variant
'
Sheet2Value = Sheets("Sheet2").Range("A:A").Value
Sheet1Value = Sheets("Sheet1").Range("A:A").Value
'
If Sheet2Value = Sheet1Value Then
Sheets("BMAC=N").EntireRow.Hidden = False
Else
Sheets("BMAC=N").EntireRow.Hidden = True
End If
I get a type mismatch error but I'm not sure exactly why. I chose variant because I don't know what I'm doing, but both columns in excel will be set to "General".
Can anyone help with this? What concept am I missing?
Thanks so much for your time.
Few things:
you cannot compare entire column:
Sheet2Value = Sheets("Sheet2").Range("A:A").Value
you need to loop through the collection of cells, see this: Fast compare method of 2 columns
you cannot hide row without defining a range to hide
Sheets("BMAC=N").Range("Some_address").EntireRow.Hidden
Finally, i'd suggest to change your code to shortest way:
Sheets("BMAC=N").Range("A1").EntireRow.Hidden = (value1<>value2)
Good luck!