I am getting a formula error message: Run-time error 1004, for the second recurrence of a formula in the code; the code section in question as follows, for quick reference I pasted the two formulas just below, the first one runs OK, the second one gives the error that I cannot figure out.
ActiveWorkbook.Names.Add Name:="pivotsourceFGPO", RefersToR1C1:=swaFormula (no errors when running the macro)
ActiveWorkbook.Names.Add Name:="pivotsourceorderbase", RefersToR1C1:=swaFormula (FORMULA giving error)
Code: (partial)
swaFormula = "=OFFSET(" & _
ActiveWorkbook.Worksheets(ActiveSheet.Index).Name & "!R" & ActiveCell.Row & "C" & ActiveCell.Column & ",0,0,COUNTA(" & _
ActiveWorkbook.Worksheets(ActiveSheet.Index).Name & "!C" & ActiveCell.Column & ") -" & swarow & ",COUNTA(" & _
ActiveWorkbook.Worksheets(ActiveSheet.Index).Name & "!R" & ActiveCell.Row & ")-" & swacol & ")"
ActiveWorkbook.Names.Add Name:="pivotsourceFGPO", RefersToR1C1:=swaFormula
Dim PTCache As PivotCache
Dim pt As PivotTable
Dim WS As Worksheet
Dim pvtfld As PivotField
' define the range which serves as the data range
Set WS = Sheets.Add ' add new sheet to hold the pivot table
Set PTCache = ActiveWorkbook.PivotCaches.Add(SourceType:=xlDatabase, SourceData:="=pivotsourceFGPO")
' Create the pivot table
Set pt = PTCache.CreatePivotTable(TableDestination:=WS.Range("A1"), TableName:="FGPOPivot")
ActiveWorkbook.ShowPivotTableFieldList = True
pt.PivotFields("Key").Orientation = xlRowField
pt.PivotFields("Key").Position = 1
pt.PivotFields("MTL").Orientation = xlRowField
pt.PivotFields("MTL").Position = 2
pt.PivotFields("Size Code").Orientation = xlRowField
pt.PivotFields("Size Code").Position = 3
pt.PivotFields("Week").Orientation = xlColumnField
pt.PivotFields("Week").Position = 1
pt.AddDataField pt.PivotFields("Wip Qty"), "Sum of Wip Qty", xlSum
'Order base 1 pivot
Sheets("Order base (1)").Select
Range("A1").Select
swarow = ActiveCell.Row - 1
swacol = ActiveCell.Column - 1
' make it comma and not colon
swaFormula = "=OFFSET(" & _
ActiveWorkbook.Worksheets(ActiveSheet.Index).Name & "!R" & ActiveCell.Row & "C" & ActiveCell.Column & ",0,0,COUNTA(" & _
ActiveWorkbook.Worksheets(ActiveSheet.Index).Name & "!C" & ActiveCell.Column & ") -" & swarow & ",COUNTA(" & _
ActiveWorkbook.Worksheets(ActiveSheet.Index).Name & "!R" & ActiveCell.Row & ")-" & swacol & ")"
ActiveWorkbook.Names.Add Name:="pivotsourceorderbase", RefersToR1C1:=swaFormula (FORMULA giving error)
You are relying on the ActiveCell property. There are better ways¹ to reference cells than that but if those 'best practises can be disregarded for a minute, the ActiveCell knows what its .Parent worksheet and workbook are.
Additionally, with no actual worksheet names provided, there is no guarantee that the ActiveSheet's .Name property does not contain a space and may require ticks (e.g. ') to wrap it. Either those should be added as a matter of course or the Range.Address property should be used to generate the strings for the cell range(s).
The non-volatile INDEX function could concevably replace the volatile² OFFSET function but I don't know enough about the layout of your data to suggest an infallible substitute formula.
Dim swaFormula As String, rngName As String
Dim swaRow As Long, swaCol As Long
rngName = "pivotSourceOrderBase"
swaRow = 0: swaCol = 0
With ActiveCell
swaFormula = "=OFFSET(" & _
.Cells(1).Address(external:=True, ReferenceStyle:=xlR1C1) & _
", 0, 0, COUNTA(" & _
.Cells(1).EntireColumn.Address(external:=True, ReferenceStyle:=xlR1C1) & _
")-" & swaRow & ", COUNTA(" & _
.Cells(1).EntireRow.Address(external:=True, ReferenceStyle:=xlR1C1) & _
")-" & swaCol & ")"
Debug.Print swaFormula '<~~ check the formula in the Immediate window
On Error Resume Next 'may be needed for the next line
.Parent.Parent.Names(rngName).Delete
On Error GoTo 0
.Parent.Names.Add Name:=rngName, RefersToR1C1:=swaFormula
End With
Walk through this and check the formula in the VBE's Immediate window before attempting to apply it to the named range creation.
¹ See How to avoid using Select in Excel VBA macros for more methods on getting away from relying on select and activate to accomplish your goals.
² Volatile functions recalculate whenever anything in the entire workbook changes, not just when something that affects their outcome changes. Examples of volatile functions are INDIRECT, OFFSET, TODAY, NOW, RAND and RANDBETWEEN. Some sub-functions of the CELL and INFO worksheet functions will make them volatile as well.
Related
As the title says, I am unable to pass a String parameter through an OnAction that occurs when a checkbox is checked. I have successfully passed two integer values to the sub when the checkbox is checked, but now I need to also pass a String parameter (the String is actually the name of the current Worksheet).
This is currently what it looks like:
'Start of for loop which will run from the lower bound of esq to the upper bound.
For i = LBound(esq) To UBound(esq)
'Inserts a row at the specified location, the current row + 1 + the value of i (0 to 12 depending on which run of the loop it is currently on).
workSource.Rows(rowPos + 1 + i).Insert
'Sets cb as equal to the specified cell in the newly inserted row.
Set cb = workSource.CheckBoxes.Add(Cells(rowPos + 1 + i, colPos + 1).Left, Cells(rowPos + 1 + i, colPos + 1).Top, _
Cells(rowPos + 1 + i, colPos + 1).Width, Cells(rowPos + 1 + i, colPos + 1).Height)
'Start of With which sets the attributes of cb.
With cb
'Sets the caption as the current element of esq.
.Caption = esq(i)
'Links the checkbox with the cell directly beneath it.
.LinkedCell = Cells(rowPos + 1 + i, colPos + 1).Address
'Adds a macro which will be activated when it is clicked. The cell's row and column position will be passed as parameters to the macro.
.OnAction = "'ProcessCheckBox " & rowPos + 1 & "," & colPos + 1 + i & "," & currentName & "'"
'.OnAction = "'" & ThisWorkSheet.Name & "'!ProcessCheckBox"
'.OnAction = "'ProcessCheckBox " & rowPos + 1 & "," & colPos + 1 + i & "," & """SES""" & "'"
'.OnAction = "'ProcessCheckBox " & currentName & "'"
'End of With.
End With
'Starts next run of loop and increments i.
Next i
There are three commented out lines of OnAction that I attempted to experiment with in order to get just the string to be passed. Unfortunately, none of them worked. Here is the start of the code for the ProcessCheckBox sub:
'Sub to process when a checkbox has been changed.
Sub ProcessCheckBox(ByVal rowPos As Integer, ByVal colPos As Integer, ByVal currentSheet As String)
'Sub ProcessCheckBox(ByVal currentSheet As String)
MsgBox currentSheet
'Declares a worksheet object named currentSheet.
Dim activeSheet As Worksheet
'Sets currentSheet equal to the active worksheet.
Set activeSheet = ThisWorkbook.Worksheets(currentSheet)
'Set currentSheet = ActiveSheet
After clicking the checkbox, a msgbox appears that is completely blank, and then I run into an error where it says the subscript is out of range.
I gather from this that the sub is being called, the String value is just not being passed along. The string value in the first sub (currentName) does have a value, as I can print it out and use it for calculations just fine.
I think the problem is in the OnAction line itself. It took me a while to figure out how to pass the integer values due to not knowing the correct number of single and double quotes to use. I think it has to do with this, however, all of the other examples I saw passed String values like this. I even experimented by adding or removing quotes just to see if it would work out and nothing.
Other errors I thought it might be: a sub has a limit to how many/large parameters can be passed to it, only parameters of a single type can be passed (either String or Integer). Neither of these make sense because I have encountered many examples that pass much more data across many different types to a sub.
Thank you to the people who answered, but neither of the solutions offered worked. I've been testing the macro and it appears no matter what I do, it will not pass a string as a parameter, either alone or with other parameters. I don't know why.
Here are the two lines in question I have narrowed it down to :
.OnAction = "'ProcessCheckBox " & colPos + 1 & "," & rowPos + 1 + i & ",""" & nameSheet & """'"
And the first line of the sub :
Sub ProcessCheckBox(ByVal colPos As Integer, ByVal rowPos As Integer, ByVal sheetName As String)
Ticking the checkbox gives me an error saying "Argument Not Optional." However, it doesn't allow me to go into debug mode, and it doesn't highlight the specific line either, although I have tested it and believe these two lines to be the problem.
I've given up on figuring VBA's single and double quotes and acknowledge that I never needed anything to be passed as argument that wasn't available in the workbook in which the check box resides. Therefore I can easily get all the information I might want to pass directly from the worksheet.
Where that may not be enough, I also get access to the CheckBox object itself. All my needs for arguments can be satisfied completely without any quotation marks.
Private Sub CheckBox1_Click()
Dim ChkBox As Shape
Set ChkBox = ActiveSheet.Shapes(Application.Caller)
MsgBox ChkBox.Parent.Name & vbcr & _
ChkBox.OLEFormat.Object.Name
End Sub
Here are 3 possible solutions for your problem, all involving the Application.Caller.
Please run this code on your project.
Sub CheckBox1_Click()
Dim ChkBox As Shape
Dim WsName As String, Rpos As Long, Cpos As Long
Dim Cell As Range
' Solution 1
WsName = ActiveSheet.Shapes(Application.Caller).OLEFormat.Object.Parent.Name
MsgBox "You already know how to pass the cell coordinates" & vbCr & _
"Just get the Sheet name from here:" & vbCr & _
"Sheet name is """ & WsName & """"
Set ChkBox = ActiveSheet.Shapes(Application.Caller)
' Solution 2
Set Cell = ChkBox.OLEFormat.Object.TopLeftCell
Rpos = Cell.Row
Cpos = Cell.Column
WsName = Cell.Worksheet.Name
MsgBox "Solution 2" & vbCr & _
"The checkbox Top Left is aligned with the" & vbCr & _
"Linked Cell's Top Left:-" & vbCr & _
"Row number = " & Rpos & vbCr & _
"Column number = " & Cpos & vbCr & _
"Worksheet name = " & WsName & vbCr & _
"If Alignment of underlying cell and TopLeft" & vbCr & _
"isn't perfect, modify the placement in your other code." & vbCr & _
"Here is the TopLeft address:-" & vbCr & _
"TopLeftCell address = " & Cell.Address
' Solution 3
Set Cell = Range(ChkBox.OLEFormat.Object.LinkedCell)
Rpos = Cell.Row
Cpos = Cell.Column
WsName = Cell.Worksheet.Name
MsgBox "Solution 3" & vbCr & _
"Get the information directly from the Linked Cell." & vbCr & _
"(This is probably the one you are interested in):-" & vbCr & _
"Row number = " & Rpos & vbCr & _
"Column number = " & Cpos & vbCr & _
"Worksheet name = " & WsName & vbCr & _
"This method might fail if the linked cell" & vbCr & _
"is altered, perhaps manually."
End Sub
I created a function in Excel VBA:
Function codeList(Criteria As String, LookupRange As Range, ValueRange As Range, delimiter As String)
It works great when I pass hard coded ranges to it like this:
ActiveCell.FormulaR1C1 = "=codelist(RC[2],R2C4:R84C4,R2C3:R84C3,"","")"
I would like the rows to be dynamic, so instead of saying C2:C84 or D2:D84 I would like to make the C84 / D84 vary based on the number of columns that have data.
I tried to compute the last row and concatenate the ranges to make them dynamic when I call the function, but I get a compile syntax error :
Dim lastRow As Long
lastRow = Range("C" & Rows.Count).End(xlUp).Row
ActiveCell.FormulaR1C1 = "=codelist(RC[2],"R2C4:R" & lastrow &"C4", "R2C3:R" & lastrow & "C3"),"","")"
Any suggestions on how to make this work?
When you want to include double quotes inside a string, you have to use two double quotes to escape them.
ActiveCell.FormulaR1C1 = "=codelist(RC[2],R2C4:R" & lastRow & "C4, R2C3:R" & lastRow & "C3,"""")"
The four double quotes near the end convert to two double quotes (the empty string your looking for).
This way is longer, but I tend to use offsets in formulas. I find it easier to read than trying to determine where the strings begin and end
Const DBLQTE As String = """"""
ActiveCell.FormulaR1C1 = "=codelist(RC[2]," & _
Range("D2").Resize(lastRow - 1).Address(, , xlR1C1) & _
"," & _
Range("C2").Resize(lastRow - 1).Address(, , xlR1C1) & _
"," & _
DBLQTE & _
")"
Update
For a comma delimeter
ActiveCell.FormulaR1C1 = "=codelist(RC[2],R2C4:R" & lastRow & "C4, R2C3:R" & lastRow & "C3,"","")"
and
Const COMMA As String = ""","""
ActiveCell.FormulaR1C1 = "=codelist(RC[2]," & _
Range("D2").Resize(lastRow - 1).Address(, , xlR1C1) & _
"," & _
Range("C2").Resize(lastRow - 1).Address(, , xlR1C1) & _
"," & _
COMMA & _
")"
Qualify the parent worksheet and resize according to the column's populated limit. Resize every associated range that needs to be the same size.
Function codeList(Criteria As String, LookupRange As Range, ValueRange As Range, delimiter As String)
with LookupRange.parent
set LookupRange = .range(LookupRange.cells(1), .cells(.rows.count, LookupRange.cells(LookupRange.cells.count).column).end(xlup))
set ValueRange = ValueRange.cells(1).resize(LookupRange.rows.count, LookupRange.columns.count)
end with
'all the rest of the code
end function
Never use ActiveSheet or ActiveCell in a worksheet's UDF. The originating cell where the formula is in is the Application.Caller.
Im trying to create a code which will allow me to pull the average of 6 rows from a sheet called 'Raw Data' and dump it into a cell in a different worksheet, and then pull the average of the next 6 rows from 'Raw Data' and so on.
E.G. average('RawData'! A1:A6) in a new sheet A1
then
average('Raw Data'! A7:A12) In new sheet A2
etc.
So far I have managed to make the code loop in a way that I want however Im having trouble writing the actual formula in new sheet A1 and A2.
so far I have tried:
Dim address13 As String
address13 = "'Raw Data'" & "!" & Cells(start_row, RPM1300).Address & ":" & _
Cells(end_row, RPM1300).Address
ActiveCell.Offset(0, -4).Select
'1300
ActiveCell.Formula = "=Average(""" & address13 & """)"
However this returns the correct formula but with "" around it - rendering it useless.
I have also tried:
Sheets("Raw Data").Select
Dim address9 As Range
Set address9 = Range(Cells(start_row, RPM900).Address(), Cells(end_row, RPM900).Address())
Sheets("New Sheet").Select
rCell.Activate
ActiveCell.Offset(0, -5).Select
ActiveCell.Formula = "=Average(address9)"
However this just returns the name of the variable address9 in the formula rather than the actual range.
Note that RPM1300, RPM900, start_row, end_row and rCell are all variables in order for the code to loop and paste into the correct places.
Any help would be greatly apreciated
Try replacing your line:
ActiveCell.Formula = "=Average(""" & address13 & """)"
With:
ActiveCell.Formula = "=AVERAGE(" & address13 & ")"
The reason: the variable address13 is already defined as a String, that's why you don't need the extra " inside the brackets.
Code (use your first method:)
Dim address13 As String
address13 = "'Raw Data'!" & Cells(start_row, RPM1300).Address & ":" & _
Cells(end_row, RPM1300).Address
ActiveCell.Offset(0, -4).Select
ActiveCell.Formula = "=AVERAGE(" & address13 & ")"
Note: Try avoid using Select and ActiveCell , instead use referenced Ranges and Worksheets.
For instance, let's say you start from Cell A1, and you want this formula to be in Cell A5, you can use:
Range("A1").Offset(4, 0).Formula = "=AVERAGE(" & address13 & ")"
It is probably a bug in your version of Excel. Instead of
ActiveCell.Formula = "=Average(""" & address13 & """)"
try using
ActiveCell.Formula = '=Average("' & address13 & '")'
(single quotes around strings with double quotes and using only 1 double quote then).
Instead of
ActiveCell.Formula = "=Average(""" & address13 & """)"
Try
ActiveCell.Formula = "=Average("& chr(34) & address13 & chr(34) & ")"
At least here chr(34) returns the quotes you want. This may be tweaked if needed. Just change the number inside the ( )
Try using this:
Sub CellValue()
Dim adr As String
Dim sht As String
sht = "'Raw Data'"
adr = "A1:A3"
ActiveCell.Formula = "=AVERAGE(" & sht & "!" & adr & ")"
End Sub
Hope it helps :)
This formula will give you the same result and you'd be able to autofill it by dragging the cell handle.
=AVERAGE(OFFSET('Raw Data'!$A$2,ROW(A1)*6-7,0,6,1))
Filling in both formulas
Sub FillFormulas()
Const BASE_FORMULA = "=AVERAGE('Raw Data'!#Address)"
Dim lastRow As Long, x As Long
Dim Formulas
With Worksheets("Raw Data")
lastRow = .Range("A" & .Rows.Count).End(xlUp).Row / 6
End With
ReDim Formulas(1 To lastRow, 1 To 1)
With Worksheets("New Sheet")
For x = 1 To lastRow
Formulas(x, 1) = Replace(BASE_FORMULA, "#Address", .Cells((x * 6) - 5, 1).Resize(6).Address)
Next
.Range("A1").Resize(lastRow).Formula = Formulas
.Range("C1").Resize(lastRow).Formula = "=AVERAGE(OFFSET('Raw Data'!$A$2,ROW(A1)*6-7,0,6,1))"
End With
End Sub
I'm trying to use .clearcontents on range that is referenced by with some .offset, and I'm having trouble
I know that this works
Sub clear1_1()
Workbooks("xyz").Sheets("abc").range("A2:A3").ClearContents
End Sub
but if I try this it does not
Sub clear2()
Dim region As range
Set region = range("S509:AD618")
Workbooks("xyz").Worksheets("abc").range(region).ClearContents
end sub
I do understand from other postings, that it has something to do with object defyining, but I have no idea where I do mistake, what I need to write.
Final macro is run from one workbook, and is supposed to .clearcontents in other not activated workbook.
My code looks like this
sub Macro()
..... ton of code
Dim filename as string
dim sheetname as string
dim address3, address4 as string
filename = "xyz"
sheetname = "abc" ' both variables that are loaded in other part
address3 and address4 loaded in other part
'here is where i get the error
sheets(sheetname).Range(Range(address3).Offset(0, 12).Address & ":" & Range(address4).Offset(-1, 23)).ClearContents
end sub
I can probably bypass it with .value=""
But I'm looking to learn. Thank you for any response in advance.
EDIT 1
Hi Scott, doesn't make it. Posting bigger part of my code
If mapanchorsuccess = True And map1success = True And map2success = True Then
If Workbooks(Filename).Sheets(startws).Range(address1).Offset(10, 13).HasFormula = True Then
With Workbooks(wbm).Sheets("Report") 'report
.Range("A" & reportrow).Value = runnumber
.Range("B" & reportrow).Value = Filename
.Range("C" & reportrow).Value = Workbooks(Filename).Sheets(startws).Name
.Hyperlinks.Add anchor:=.Range("D" & reportrow), Address:=FilePath & Filename, SubAddress:=Workbooks(Filename).Sheets(startws).Name & "!A1"
.Range("E" & reportrow).Value = "Error"
.Range("F" & reportrow).Value = "rolling probably done already in this sheet"
reportrow = reportrow + 1
End With
Else
With Workbooks(Filename).Sheets(startws)
.Range(Range(address1).Offset(0, 12).Address & ":" & Range(address2).Offset(0, 14).Address).Copy _
Range(Range(address1).Address & ":" & Range(address2).Offset(0, 2).Address)
Application.CutCopyMode = False
.Range(Range(address1).Offset(0, 16).Address & ":" & Range(address2).Offset(0, 16).Address).Copy _
Range(Range(address1).Offset(0, 3).Address & ":" & Range(address2).Offset(0, 23).Address)
Application.CutCopyMode = False
With Workbooks(wbm).Sheets("Report") 'report
.Range("A" & reportrow).Value = runnumber
.Range("B" & reportrow).Value = Filename
.Range("C" & reportrow).Value = Workbooks(Filename).Sheets(startws).Name
.Hyperlinks.Add anchor:=.Range("D" & reportrow), Address:=FilePath & Filename, SubAddress:=Workbooks(Filename).Sheets(startws).Name & "!A1"
.Range("E" & reportrow).Value = "Completed"
.Range("F" & reportrow).Value = "region1 rolled forward"
reportrow = reportrow + 1
End With
.Range(Range(address3).Offset(0, 12).Address & ":" & Range(address4).Offset(-1, 23).Address).Copy _
Range(Range(address3).Address & ":" & Range(address4).Offset(-1, 11).Address)
'///// here the error 1004 occurs
.Range(Range(address3).Offset(0, 12).Address & ":" & Range(address4).Offset(-1, 23).address).clearcontent
End With
End If
End If
The workbook and sheet need to be set with the variable.
Then when using it since it is a range itself just refer to it.
Sub clear2()
Dim region As range
Set region = Workbooks("xyz").Worksheets("abc")range("S509:AD618")
region.ClearContents
end sub
As to your next code; that is a different problem. The ranges inside the () need to allocated to the correct sheet parentage or it will use the active sheet.
The easiest is with a With block:
With sheets(sheetname)
.Range(.Range(address3).Offset(0, 12), .Range(address4).Offset(-1, 23)).ClearContents
End With
I had this same issue, but it turned out to be very simple. I had a row of cells merged together between columns E and F, so when I used this command I had to set the ClearContents from the top corner of my E column to the bottom row of my F column.
What did not work:
Range("E1:E10").Clear Contents
What did work:
Range("E1:F10").ClearContents
I can't believe such a simple thing left me so thwarted.
I'm working with some data on Excel 2011 for Mac (version 14.3.1) that I need to graph and add more data later on. To do that, I'm using names for ranges as it is explained here. Basically, create Name ranges with the formula =OFFSET($A$2,0,0,COUNTA($A:$A)-1) (in spanish: =DESREF($A$2,0,0,CONTARA($A:$A)-1)).
I have many columns, so I wrote this vba to do it for me:
Sub Botón6_AlHacerClic()
For i = 1 To Columns.Count
Names.Add Name:=ActiveSheet.Name & Range(Cells(1, i).Address).Value, RefersTo:="=DESREF(" & Cells(2, i).Address & ",0,0,CONTARA(" & Replace(Cells(1, i).Address, "$1", "") & ":" & Replace(Cells(1, i).Address, "$1", "") & ")-1)"
Next i
End Sub
Where:
Cells(2, i).Address is the cell id for the second row (Eg: $A$2)
Replace(Cells(1, i).Address, "$1", "") is the row letter (Eg: $A)
The problem I'm having is that when entering the names manually, it replaces the formula =DESREF($A$2,0,0,CONTARA($A:$A)-1) with =DESREF(Sheet1!$A$2,0,0,CONTARA(Sheet1!$A:$A)-1) which is fine and works great. But when I do it by the vba, it replaces it with =Sheet1!DESREF(Sheet1!$A$2,0,0,CONTARA(Sheet1!$A:$A)-1) that doesn't work.
I tried with the different options of the Add manual and even tried to run this code after the names are created to eliminate the Sheet1! at the beginning but at the end they keep the Sheet1!:
Sub Botón7_AlHacerClic()
Set nms = ActiveWorkbook.Names
For i = 1 To nms.Count
nms(i).RefersTo = Replace(nms(i).RefersTo, ActiveSheet.Name & "!DESREF", "DESREF")
Next i
End Sub
Another thing I tried was to replace the Sheet1!DESREF for something that is not a function:
Sub Botón7_AlHacerClic()
Set nms = ActiveWorkbook.Names
For i = 1 To nms.Count
nms(i).RefersTo = Replace(nms(i).RefersTo, ActiveSheet.Name & "!DESREF", "DESREFF")
Next i
End Sub
And in this case it gives me: =DESREFF($A$2,0,0,CONTARA($A:$A)-1) But I haven't find a way to do it with the DESREFwithout adding the Sheet1!
How can I prevent the Sheet1! from appearing at the beginning?
Thank you
I've tried with different versions of Excel and it seems to be a bug in Excel 2011 for Mac (version 14.3.1).
I tried it in the following versions and it didn't add the Sheet1! at the beginning:
Excel for Mac 14.3.9
Excel for Windows 16.0.6001.1054
The problem now with both of those versions is the following:
I have a column with the following cells:
C1-> data
C2-> 400
C3-> 100
C4-> 100
And after C5 empty. I run the script to create the names:
Sub Botón6_AlHacerClic()
For i = 1 To Columns.Count
Names.Add Name:=ActiveSheet.Name & Range(Cells(1, i).Address).Value, RefersTo:="=DESREF(" & Cells(2, i).Address & ",0,0,CONTARA(" & Replace(Cells(1, i).Address, "$1", "") & ":" & Replace(Cells(1, i).Address, "$1", "") & ")-1)"
Next i
End Sub
And it created me the name Sheet1data with the reference: =DESREF(Sheet1!$C$2;0;0;CONTARA(Sheet1!$C:$C)-1) which is correct. But if I go to any cell and insert the formula =SUM(Sheet1data) it resolves with a formula error #Name?, even though explaining the formula seems to point to the right cells.
More strange, if after creating it I go to edit the name and just hit Enter, the formula works automatically and presents 600. If I go again to the name editor it shows =DESREF(Sheet1!$C$2;0;0;CONTARA(Sheet1!$C:$C)-1), which is the same as before.
Finally I found this web with examples where there was one explaining something similar to what I wanted to do:
Sub DynamicNames()
Dim LastCol As Long, _
LabelRow As Long, _
Col As Long
Dim sName As String
Dim c As Range
Dim Sht As String
'assign row and column parameters
'**adjust for the row containing your headings
LabelRow = 1
LastCol = Range("IV1").End(xlToLeft).Column
'grab sheet name
Sht = "'" & ActiveSheet.Name & "'"
For Each c In Range(Cells(LabelRow, 1), Cells(LabelRow, LastCol))
Col = c.Column
sName = c.Value
If Len(sName) > 1 Then
'replace spaces with underscores
sName = Replace(sName, " ", "_", 1)
'create the name
ActiveWorkbook.Names.Add Name:=sName, RefersToR1C1:= _
"=OFFSET(" & Sht & "!R2C" & Col & ",0,0,COUNTA(" & Sht & "!C" & Col & ")-1,1)"
End If
Next c
End Sub
The main difference is that they where using RefersToR1C1 instead of RefersTo, so I changed it but it still wasn't working. Finally I changed the formulas to english even though I had to write them in spanish by hand and that did the final trick: Names.Add Name:=ActiveSheet.Name & Range(Cells(1, i).Address).Value, RefersToR1C1:="=OFFSET(" & ActiveSheet.Name & "!R2C" & Cells(2, i).Column & ",0,0,COUNTA(" & ActiveSheet.Name & "!C" & Cells(2, i).Column & ")-1)"
So, the problems where:
The Excel 2011 for Mac (version 14.3.1) seems to have a bug.
Using RefersToR1C1 instead of RefersTo makes it easier to work with vba formulas and maybe it helped.
Even though in all my Excel I use spanish formulas, the ones in vba have to be in english. (I tried the parameter _ RefersToR1C1Local_ but it gave me an error).
Finally, the code that worked:
Sub Botón6_AlHacerClic()
For i = 1 To Columns.Count
Names.Add Name:=ActiveSheet.Name & Range(Cells(1, i).Address).Value, RefersToR1C1:="=OFFSET(" & ActiveSheet.Name & "!R2C" & Cells(2, i).Column & ",0,0,COUNTA(" & ActiveSheet.Name & "!C" & Cells(2, i).Column & ")-1)"
Next i
End Sub
I hope it helps someone out there :)