The FormulaR1C1 Method doesn't work as it's supposed to.
objExcel = CreateObject("Excel.Application")
objWorkbook = objExcel.Workbooks.Add
Dim Formula As String
Formula = "=SUMME(Z1S1;Z2S1)"
For i = 1 To 5 Step 1
objWorkbook.Worksheets("Tabelle1").Cells(i, 1).FormulaR1C1 = 5
objWorkbook.Worksheets("Tabelle1").Cells(i, 5).FormulaR1C1 = "Text"
objWorkbook.Worksheets("Tabelle1").Cells(i, 3).FormulaR1C1 = Formula
Next
This should give me 10 in the third column 5 times, but it doesn't. I even tried it with:
Formula = "=SUMME(Z[0]S[-2];Z[1]S[-2])"
but that doesn't work either. The Loop just breaks when coming to the assigment line :( . If I try it with
Formula = "=SUMME(Z1S1,Z2S1)"
It executes completely but it doesn't work for excel because then it says =SUMME('Z1S1';'Z2S1') in the Excel Field
You have to use the Range.FormulaLocal property or Range.FormulaR1C1Local property if you plan to use a string that contains non-EN-US function. VB.Net expects a EN-US formula and will translate that to the regional language of the worksheet.
Formula = "=SUM(A1, B2)"
'or depending on your requiements,
Formula = "=SUM(A1:B2)"
.Formula = Formula
Formula = "=SUM(R1C1, R2C2)"
'or depending on your requiements,
Formula = "=SUM(R1C1:R2C2)"
.FormulaR1C1 = Formula
Formula = "=SUMME(Z1S1;Z2S1)"
'or depending on your requirements,
Formula = "=SUMME(Z1S1:Z2S1)"
.FormulaLocalR1C1 = Formula
Don't confuse xlA1 cell references with xlR1C1 references. R23 would mean Cells(23, 18) in xlA1 and 23:23 in xlR1C1.
Note that using the Range.Formula property or Range.FormulaR1C1 property enforces the use of a comma (EN-US standard) instead of a semicolon as a system list separator.
Range.Formula property
Range.FormulaR1C1 property
Range.FormulaLocal property
Range.FormulaR1C1Local property
Related
The Range.SpecialCells method can be used to return a Range object meeting certain criteria. The type of criteria is specified using an xlCellType constant.
One of those constants (xlCellTypeBlanks) is described as referring to "Empty cells" with no further elaboration.
Does anyone know what definition of "Empty" this method uses? Does it include cells with no values/formulas but various other features (data validation, normal formatting, conditional formatting, etc)?
That type includes the subset of cells in a range that contain neither constants nor formulas. Say starting with an empty sheet we put something in A1 and A10 and then run:
Sub ExtraSpecial()
Set r = Range("A:A").SpecialCells(xlCellTypeBlanks)
MsgBox r.Count
End Sub
we get:
Formatting and Comments are not included. Also note that all the "empty" cells below A10 are also ignored.
Papalew's response noted that "xlCellTypeBlanks" excludes any cells not within a specific version of the "used range" that's calculated in the same way as the special cell type "xlCellTypeLastCell". Through testing I've discovered that "xlCellTypeLastCell" returns the last cell of the "UsedRange" property as of the last time the property was calculated.
In other words, adding a line that references "UsedRange" will actually change the behavior of the SpecialCells methods. This is such unusual/unexpected behavior that I figured I'd add an answer documenting it.
Sub lastCellExample()
Dim ws As Worksheet
Set ws = Sheets.Add
ws.Range("A1").Value = "x"
ws.Range("A5").Value = "x"
ws.Range("A10").Value = "x"
'Initially the "UsedRange" and calculated used range are identical
Debug.Print ws.UsedRange.Address
'$A$1:$A$10
Debug.Print ws.Range(ws.Range("A1"), _
ws.Cells.SpecialCells(xlCellTypeLastCell)).Address
'$A$1:$A$10
Debug.Print ws.Cells.SpecialCells(xlCellTypeBlanks).Address
'$A$2:$A$4,$A$6:$A$9
'After deleting a value, "UsedRange" is recalculated, but the last cell is not...
ws.Range("A10").Clear
Debug.Print ws.Range(ws.Range("A1"), _
ws.Cells.SpecialCells(xlCellTypeLastCell)).Address
'$A$1:$A$10
Debug.Print ws.Cells.SpecialCells(xlCellTypeBlanks).Address
'$A$2:$A$4,$A$6:$A$10
Debug.Print ws.UsedRange.Address
'$A$1:$A$5
'...until you try again after referencing "UsedRange"
Debug.Print ws.Range(ws.Range("A1"), _
ws.Cells.SpecialCells(xlCellTypeLastCell)).Address
'$A$1:$A$5
Debug.Print ws.Cells.SpecialCells(xlCellTypeBlanks).Address
'$A$2:$A$4
End Sub
The definition does indeed contain the idea of having nothing in the cell, i.e. it excludes any cell that contains either:
a numerical value
a date or time value
a text string (even an empty one)
a formula (even if returning an empty string)
an error
a boolean value
But it also excludes any cell that’s not within the range going from A1 to the last used cell of the sheet (which can be identified programmatically through ws.cells.specialCells(xlCellTypeLastCell), or by using the keyboard Ctrl+End).
So if the sheet contains data down to cell C10 (i.e. Ctrl+End brings the focus to cell C10), then running Range("D:D").specialCells(xlCellTypeBlanks) will fail.
NB The range A1 to LastCellUsed can sometimes be different from the used range. That would happen if some rows at the top and/or some columns at on the left never contained any data.
On the other hand, cells that fit the empty definition above will be properly identified no matter any of the followings:
size or colour of font
background colour or pattern
conditional formatting
borders
comments
or any previous existence of these that would later have been cleared.
A bit beside the main subject, let me ask a tricky question related to how the term BLANK might be defined within Excel:
How can a cell return the same value for CountA and CountBlank?
Well, if a cell contains ' (which will be displayed as a blank cell), both CountA and CountBlank will return the value 1 when applied to that cell. My guess is that technically, it does contain something, though it is displayed as a blank cell. This strange feature has been discussed here.
Sub ZeroLengthString()
Dim i As Long
Dim ws As Worksheet
Set ws = ActiveSheet
ws.Range("A2").Value = ""
ws.Range("A3").Value = Replace("a", "a", "")
ws.Range("A4").Value = """"
ws.Range("A6").Value = "'"
ws.Range("A7").Formula= "=if(1=2/2,"","")"
ws.Range("B1").Value = "CountA"
ws.Range("C1").Value = "CountBlank"
ws.Range("B2:B7").FormulaR1C1 = "=CountA(RC[-1])"
ws.Range("C2:C7").FormulaR1C1 = "=CountBlank(RC[-2])"
For i = 2 To 7
Debug.Print "CountA(A" & i & ") = " & Application.WorksheetFunction.CountA(ws.Range("A" & i))
Debug.Print "CountBlank(A" & i & ") = " & Application.WorksheetFunction.CountBlank(ws.Range("A" & i))
Next i
End Sub
In this example, both lines 6 & 7 will return 1 for both CountA and CountBlank.
So the term Blank doesn’t appear to be defined a unique way within Excel: it varies from tool to tool.
I start my adventure with VBA. I would like to create formula on VBA, use vlookup but something is going wrong with this.
Also I would like to implement vlookup for cells, when
cells from deferent column will be filled
( for example if WB_WS_Pricing.Range("A4")<>0 then
WB_WS_PRICING.Range("CX4") = "=IFNA(VLOOKUP(Delivering!E4,DATA!A:I,9,0),"")"
Sub formula()
Set WB_CMSO_MASS_IBERIA = ThisWorkbook
Set WB = ThisWorkbook
Set WB_WS_PRICING = WB.Sheets("Pricing")
Set WB_WS_HEADER = WB.Sheets("Header")
Set WB_WS_DATA = WB.Sheets("DATA")
Set WB_WS_Extension = WB.Sheets("Extension")
Set WB_WS_DELIVERING = WB.Sheets("Delivering")
WB_WS_PRICING.Range("CX4") = "=IFNA(VLOOKUP(Delivering!E4,DATA!A:I,9,0),"")"
End Sub
Enyone has idea what is wrong?? For me the formula seems be fine...
You need to escape the double quotes in your formula with an extra quote in front of each (ie """" not "")
WB_WS_PRICING.Range("CX4") = "=IFNA(VLOOKUP(Delivering!E4,DATA!A:I,9,0),"""")"
Encountering an issue in a VBA regarding vlookup function.
I have 2 comboboxes and 6 Textboxs for user input.
I want to use a vlookup (or index,Match(),Match()) to look up a cell in a data table and assign the values from the textboxes to these cells.
When I run the code for what I believe should work, it is returning object errors.
Private Sub CommandButton2_Click()
Dim MonthlyTable As Range
Set MonthlyTable = Sheets("DATA Monthly").Range("A6:AE400")
Dim ColumnRef As Range
Set ColumnRef = Sheets("Drivers").Range("N11")
' Assign CB2 value to M11 cell reference so it can be converted to a column ref in N11.
Sheets("Drivers").Range("M11").Value = ComboBox2.Value
Dim CB1Value As String
CB1Value = "Joiners" & ComboBox1.Value
Dim CB2Value As String
CB2Value = ComboBox2.Value
MsgBox CB1Value & " " & CB2Value
Dim tb1value As Range
tb1value = Application.WorksheetFunction.VLookup(CB1Value, MonthlyTable, ColumnRef, False)
tb1value.Value = TextBox1.Value
Unload Me
End Sub
I am at a loss for what to do here as I feel like it should be this simple!
Thanks in advance.
Edit. Further digging indicates that you cannot select a cell you are vlookup'ing as this commands only returns a value it does not actually select the cell for my intents and purposes.
not really clear to me you actual aim, but just following up your desire as stated by:
I want to use a vlookup (or index,Match(),Match()) to look up a cell
in a data table and assign the values from the textboxes to these
cells
you may want to adopt the following technique:
Dim tb1value As Variant '<--| a variant can be assigned the result of Application.Match method and store an error to be properly cheeked for
tb1value = Application.Match(CB1Value, MonthlyTable.Column(1), 0) '<--| try finding an exact match for 'CB1Value' in the first column of your data range
If Not IsError(tblvalue) Then MonthlyTable(tb1value, columnRef.Value).Value = TextBox1.Value '<--| if successful then write 'TextBox1' value in data range cell in the same row of the found match and with `columnRef` range value as its column index
Excel uses worksheet functions to manipulate data, VBA has different tools, and when you find yourself setting cell values on a sheet via VBA so that some worksheet function can refer to them it is time to look for a true VBA solution. I suggest the following which, by the way, you might consider running on the Change event of Cbx2 instead of a command button.
Private Sub Solution_Click()
' 24 Mar 2017
Dim MonthlyTable As Range
Dim Rng As Range
Dim Lookup As String
Dim Done As Boolean
Set MonthlyTable = Sheets("DATA Monthly").Range("A2:AE400")
' take the lookup value from Cbx1
Lookup = ComboBox1.Value
Set Rng = MonthlyTable.Find(Lookup)
If Rng Is Nothing Then
MsgBox Chr(34) & Lookup & """ wasn't found.", vbInformation, "Invalid search"
Else
With ComboBox2
If .ListIndex < 0 Then
MsgBox "Please select a data type.", vbExclamation, "Missing specification"
Else
TextBox1.Value = MonthlyTable.Cells(Rng.Row, .ListIndex + 1)
Done = True
End If
End With
End If
If Done Then Unload Me
End Sub
There are two points that need explanation. First, the form doesn't close after a rejected entry. You would have to add a Cancel button to avoid an unwanted loop where the user can't leave the form until he enters something correct. Note that Done is set to True only when the search criterion was found And a value was returned, and the form isn't closed until Done = True.
Second, observe the use of the ListIndex property of Cbx2. All the items in that Cbx's dropdown are numbered from 0 and up. The ListIndex property tells which item was selected. It is -1 when no selection was made. If you list the captions of your worksheet columns in the dropdown (you might do this automatically when you initialise the form) there will be a direct relationship between the caption selected by the user (such as "Joiners") and the ListIndex. The first column of MonthlyTable will have the ListIndex 0. So you can convert the ListIndex into a column of MonthlyTable by adding 1.
I think it is better to use "find" in excell vba to select a cell instead of using vlookup or other methods.
In recorded VBA macros, it seems that their formulas use R1C1 reference style. For instance, to fill in B4 with B2+1:
Range("B4").Select
ActiveCell.FormulaR1C1 = "=R[-2]C+1"
Does anyone know if it is possible to switch off this mode? For instance, let recorded macro look like:
Range("B4").Select
ActiveCell.Formula = "=B2+1"
I believe you cannot do that. The macro will always record in R1C1 style.
You can always switch the style but it will only be applied to the worksheet and if you record a macro it will still show R1C1 reference style.
It is very easy to understand the R1C1 style
In R1C1 reference style, the range is referred by how far the cells are located from the cell you are calling. For example, if you have 5 values from R1C1 to R5C1 and the range is called from R7C2, then the range would be R[-6]C[-1]:R[-2]C[-1]. Here the first cell in the range is 6 rows before the cell R7C2 and 1 column before the cell R7C2 and similarly for the last cell in the range.
If I take your example then "=R[-2]C+1" means that the formula is referring to a row which is two rows up (-2) and in the same column (0). Your formula is same as "=R[-2]C[0]+1"
EDIT
Here is a small function that I wrote which can help you convert R1C1 to A1 string
Sub Sample()
'~~> This will give you $B$2
Debug.Print R1C12A1("B4", "R[-2]C")
'~~> This will give you E227
Debug.Print R1C12A1("O9", "R[218]C[-10]", True)
'~~> This will give you $Y$217
Debug.Print R1C12A1("O9", "R[208]C[10]")
End Sub
Function R1C12A1(baseCell As String, sRC As String, Optional RemDollar As Boolean = False) As String
Dim MyArray() As String
Dim r As Long, c As Long
sRC = Replace(sRC, "R", "")
If Left(sRC, 1) = "C" Then
r = 0
Else
r = Replace(Replace(Split(sRC, "C")(0), "[", ""), "]", "")
End If
If Right(sRC, 1) = "C" Then
c = 0
Else
c = Replace(Replace(Split(sRC, "C")(1), "[", ""), "]", "")
End If
If RemDollar = False Then
R1C12A1 = Range(baseCell).Offset(r, c).Address
Else
R1C12A1 = Replace(Range(baseCell).Offset(r, c).Address, "$", "")
End If
End Function
Note: I have not done any error handling here. I am sure you can incorporate that if needed.
There used to be a facility to toggle relative reference when recording a macro.
When you have started recording, in the macro toolbar - near the stop button - there was a button to toggle relative reference; is this not the same as toggling R1C1 ? or isn't this available anymore?
I never bothered toggling it myself as like Siddharth says the R1C1 isn't too tricky to understand plus, irrespective of whatever you do, the VBA will need some editing so at the same time if you wish to use other syntax it's easy enough to change.
I've just played around with the following but it doesn't seem to help so maybe I'm mixing up the use of this button with R1C1...
How do I left justify my columns in Excel programmatically in VB? I have a VB program that is writing an excel file based off of certain information. I have tried using:
oSheet.Columns.HorizontalAlignment.Left()
This works against columns with text. I have multiple columns that are strictly numbers. This function will not work against columns with Numeric Cells.
Below is the MissingMemberException I keep getting:
Public member 'Left' on type 'Integer' not found.
Range.HorizontalAlignment is a property that requires an integer constant. Left is xlLeft. xlLeft evaluates to -4131. xlDistributed is -4117, xlRight is -4152, xlCenter is -4108, and xlJustify is -4130.
HorizontalAlignment should work for both text and numbers. You should specify the value for the alignment though since it is a property.
Although the #Banjoe answer will work, the documentation specifies the following valid constants for HorizontalAlignment property:
xlHAlignCenter
xlHAlignCenterAcrossSelection
xlHAlignDistributed
xlHAlignFill
xlHAlignGeneral
xlHAlignJustify
xlHAlignLeft
xlHAlignRight
I used the following, and it worked great for me:
Set objExcel = CreateObject("Excel.Application")
Set objWorkbook = objExcel.Workbooks.Add()
objExcel.Cells(1, 1).Value = "Some data"
objExcel.Cells(1, 2).Value = "More data"
Set objWorksheet = objWorkbook.Worksheets(1)
objExcel.Columns(2).Select
objExcel.Selection.EntireColumn.HorizontalAlignment = 2