I am trying to create a macro that will enter ranges within a chart's data labels via the "Label Contains: Value From Cells" option. Each label corresponds to a row within a sheet such as =Breakdown!$B$27:$K$27. I recorded a macro to find the language for this action and it came back as:
ActiveChart.SeriesCollection(i).DataLabels.Format.TextFrame2.TextRange. _
InsertChartField msoChartFieldRange, "=Breakdown!$B$27:$K$27", 0
I can loop through the SeriesCollection by "Dim i As Integer". Is there any way I can set =Breakdown!$B$27:$K$27 as a string or something with variables for the cell numbers so that I can cycle through the rows?
Using string concatenate operator & and CStr function which converts an expression into a string, it'll work out well.
"=Breakdown!$B$" & CStr(i) & ":$K$" & CStr(i)
Related
Scenario: I have a code that should write a formula to a worksheet cells. This formula is for an API to retrieve some value. My formula is inside a loop (this is done for multiple columns) and references the first row for an identifier.
The original formula:
=FS(B1;"FI(DATE,,DATE)")
The modified formula with the floating reference (inside the loop):
For i = 1 To lColumn
If wb.Worksheets("Dates").Cells(i, 1).Value <> "" Then
wb.Worksheets("Dates").Cells(i,2).value = "=FS(" & i & "1;"FI(DATE,,DATE)")"
End If
Next i
Where lColumn is some pre-defined number.
Issue: I keep getting the "Unexpected end of statement" error in the formula part of the loop.
What I already tried: I tried different variations, repositioning the "s and 's, for example:
wb.Worksheets("Dates").Cells(i,2).value = "'"=FS(" & i & "1;"FI(DATE,,DATE)")""
or
wb.Worksheets("Dates").Cells(i,2).value = "'=FS(" & i & "1;"FI(DATE,,DATE)")"
or
wb.Worksheets("Dates").Cells(i,2).value = "'""=FS(" & i & "1;"FI(DATE,,DATE)")"
and so on. But the error still persists.
Question: What is the proper way to do this operation?
Working with formulas in VBA is a little bit tricky:
To write a formula, use the range.formula property, not the .value.
You have to write the formula as if you are using an english Excel. Parameter-separator is comma (not semicolon).
If a formula needs a quote, double it so that the VBA compiler understands that you want a quote within a string.
I find it helpfull to write a formula into a variable before assigning it - you can check in the debugger if it is exactly how it should before assigning it.
To check how the formula should look like, write it into a cell, change to the VBA-editor, open the immediate window and write ? activecell.formula
Try (untested as the formula you need is not valid to us):
with wb.Worksheets("Dates")
dim f as string, adr as string
adr = cells(i, 1).address(false, false) ' get rid of Dollar signs
f = "=FS(" & adr & ",""FI(DATE,,DATE)"")"
.Cells(i, 2).formula = f
end with
wb.Worksheets("Dates").Cells(i,2).formula = "=FS(" & Cells(1, i).Address(0,0) & ";""FI(DATE,,DATE)"")"
There may be a better way to convert the column number to a letter (which is the problem you are having, along with the double quotes)!
I am trying to use the Application.VLookup function in Visual Basic to find a value in a different workbook. However, whenever I use it, it always returns #N/A.
This is the layout of my function. LastRow() just returns the row number of the last row. SHORTAGE_SBT is a variable containing the source workbook name. SBT_Last is the last row of SHORTAGE_SBT. The ID that I'm searching with in in the B column, hence why I use "B" & ind to refer to it.
For ind = 4 To LastRow()
Range("H" & ind).Select
ActiveCell.Value = Application.VLookup("B" & ind, Workbooks(SHORTAGE_SBT).Sheets(1).Range("A14:DZ" & SBT_Last), Range("DZ1").Column, False)
Next
I have tried recording a macro for VLookup to see if it would help me understand the problem. The macro gave me this function, which worked but could not be used because it contains the hardcoded file name instead of using the variable.
Range("H" & ind).FormulaR1C1 = "=VLOOKUP(RC[-6],'[filename.xls]Sheet1'!R14C1:R2382C130, COLUMN(R[-3]C[122]), FALSE)"
I cannot see any significant difference between the way the macro lays out the arguments of the function as opposed to mine, other than using more direct references. I have tried using direct numbers in my code but doing so hasn't helped either.
Application.VLookup("B" & ind, Workbooks(SHORTAGE_SBT).Sheets(1).Range("A14:DZ" & SBT_Last), Range("DZ1").Column, False)
"B" & ind will be searched for "literally"; it will not be transformed into a range address because it is interpreted here by VBA, not by Excel. Try:
Application.VLookup(Range("B" & ind), Workbooks(SHORTAGE_SBT).Sheets(1).Range("A14:DZ" & SBT_Last), Range("DZ1").Column, False)
' ^^^^^^^^^^^^^^^^
Combine the two approaches:
Range("H" & ind).FormulaR1C1 = _
& "=VLOOKUP(RC[-6],'[" & Workbooks(SHORTAGE_SBT) _
& "]Sheet1'!R14C1:R2382C130, COLUMN(R[-3]C[122]), FALSE)"
Is it possible to write a formula in VBA for excel such that there are "n" terms in the formula, with the number of terms changing as the value of "n" does?
For instance, say you wanted to code cell a1 such that it was the sum of a2 and a3. Then you wanted b1 to be the sum of b2,b3,b4,b5 and so on such that each column 1 row 1 cell for a range of cells is the sum of "n" cells below it where "n" varies from column to column. Say that all cell addresses you wanted to use are known and stored in an array.
Here is some code to better explain what I'm asking:
For i = 0 to n
Range(arr1(i)).formula = "=" & range(arr2(i)).value & "-(" _
& Range(arrk(i)).value & "+" & Range(arrk+1(i)).value & "+" _
& Range(arrk+2(i)).value & "+" & ... & ")"
Next i
So what I'm looking for is one piece of VBA code that can make a cell formula contain a dynamic number of terms. The code above would make cell a1's value = a-(b+c+d+...) where the number of terms in the bracket is variable, depending on which cell the formula is applied to.
The image here shows an example of what I want to do. I'd like some code which could take "years income" and subtract a variable amount of "expenses" from it, where the number of expenses varies each year (but the number stays fixed for that year). The code needs to use a formula so that the expenses entries can be modified by the user.
Have you tried Array Formula ? :
Array Formula :
An Excel Array Formula performs multiple calculations on one or more sets of values (the 'array arguments') and returns one or more results.
details : http://www.excelfunctions.net/Excel-Array-Formulas.html
Thanks for the suggestions everyone, I found a solution (not a particularly efficient one, but a solution nonetheless) to the conundrum today.
First I created an array which used the "pattern" of the Junk cells to list every cell address which was to be included.
Taking this array, I used a for loop to create a series of temporary arrays with the application.index command. For each temporary array, I used the Join command to turn the list of cells into a single string which I then inputted into a cell formula. Thanks to #thepiyush13 whose array.formula approach inspired this.
Here's some example code to show what I did:
' hypothetical array containing two sets of cells to use
Dim array1(0 To 1, 0 To 1) As Variant
Dim vartemp As Variant
Dim vartemptransposed As Variant
' col 1 will be used to add I10 and I13, col2 I11 and I14
array1(0, 0) = "$I$10"
array1(1, 0) = "$I$13"
array1(0, 1) = "$I$11"
array1(1, 1) = "$I$14"
For i = 1 to 2
'application.index(arr,row#,col#) to create a new array
vartemp = Application.Index(array1, 0, i)
'error if not transposed
vartemptransposed = Application.Transpose(vartemp)
randomstring = Join(vartemptransposed, ",")
totalvalue = 100
'example formula: a1 = totalvalue - sum(I10,I13). a2 = totalvalue - sum(I11,I14)
Cells(1,i).formula = "=" & totalvalue & "-SUM(" & randomstring & ")"
Next i
I needed the code to run this many many times on large lists which are generated dynamically but always hold the same pattern of where the "junk cells" are. Not included in the code, but I also used another array for the cell addresses of where to place the formula.
I have data in cells A1:A1000. It is a list of names followed by a small note, like this:
sam" fast
nick" long
tom" quick
They all have " and a space after the names and then the note. What I am trying to do is delete the everything after the name.
I was playing around with macros to try and do this, but could not get anything to work. Any idea how I might do this?
Here is a nifty trick without macros:
Select the proper range (or even just click on A to select the entire column) and then do Ctrl+F, click Replace, in Find write exactly "* and leave the Replace with box empty. Now click Replace all and tada !
It replaces everything after (and including) the quote with nothing because it uses * as a wildcard you left the replace box empty.
Edit: As suggested here is the VBA code for this:
Columns("A:A").Replace What:="""*", Replacement:="", LookAt:=xlPart
Easy! I don't know what version of Excel you are using, but in short you want to do a Convert Text to Columns and then split the cells using a delimiter of ". This will leave you with two columns, one of the data you want and one you can just delete.
Here is the walk through in Office 2010:
Highlight column A
find the Data menu
find the Convert Text to Columns menu
Pick Delimited and hit next
In the Other box, type "
hit Finish
Done! Now you have all your names in column A and you can just delete column B.
To sum up, do a "Convert Text to Columns" and then split the cells using a delimiter of ". Super easy and fast.
few options:
Replace
Range("A1:A1000").Replace """*", vbNullString
If you require to manipulate the value further then the below are more appropriate:
With Regex:
Dim str As String, strClean As String
Dim cell As Range
For Each cell In Range("A1:A1000")
With CreateObject("vbscript.regexp")
.Pattern = "\""(.*)"
.Global = True
cell = .Replace(cell, vbNullString)
End With
Next cell
Without Regex, splitting the string:
Dim strSplit() As String
Dim cell As Range
For Each cell In Range("A1:A1000")
If (cell.Value <> vbNullString) Then
cell.Value = Split(cell.Value, """")(0)
End If
Next cell
In case you want to keep your source data, you can also do it with a simple Excel formula in the next column. Assuming that your data is in column A, the following formula will return only the name: =LEFT(A1,SEARCH("""",A1)-1)
Sub Macro1()
For Row = 1 To 1000
S = Range("A" & Row).Cells.Value
Pos = InStr(S, Chr(34))
If Pos > 0 Then Range("A" & Row).Cells.Value = Left(S, Pos - 1)
Next
End Sub
Press ctrl + f, click on replace tab, type * in the find what box and then click on replace all. No need to put anything in replace box. Here you are replacing everything after ..
I have a list of city names followed by the state in which they are located all in one column in Excel. How can I delete everything after the first space so that the city name is the only thing that's left in the cell?
example: A1 = "johnson TX"
should be just A1= "johnson"
I assume you want a VBA solution since you tagged your question excel-vba.
This works:
Sub KeepCity()
Dim strCityAndState As String
Dim strCityOnly As String
strCityAndState = Range("A1").Value
strCityOnly = Left(strCityAndState, InStr(strCityAndState, " ") - 1)
Range("A2").Value = strCityOnly
End Sub
If you don't want VBA and want a cell formula instead, then #JToland's answer works fine, though this one is more concise and doesn't keep the trailing space character:
=LEFT(A1, FIND(" ",A1)-1)
Well doing something like this
=Mid(A1, 1, Find(" ",A1))
in another column should grab all text before the " ". So you could build another column with just all the city names and then you could use that column for your purposes.
If you are looking for a VBA function, you can use Left and InStr as shown below.
Dim Temp As String: Temp = "Hello_World! This is my first answer here. :D"
Temp = Left(Temp, InStr(Temp, " ")-1)
In which case, Temp will be "Hello_World!"
Use of Split function
An elegant approach is to use the first token of the Split function:
Code Example extracting from cell A1 to A2
Option Explicit
Sub KeepCity()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("MySheet") ' << Change to your sheet name
ws.[A2] = Split(ws.[A1], " ")(0)
End Sub
Alternative Syntax
Instead of cell abbreviations [A2] or [A1] you can also use:
ws.Range("A2").Value = Split(ws.Range("A1").Value, " ")(0)
Note
The resulting split 1-dimensional array is zero based, so you get the first part (or token) of the original string via index (0).
If you are looking for a second part, I recommend adding an additional delimiter value (" ") to the original string, e.g. s: MsgBox split(s & " "," ")(1). By that way you avoid error number 9 "Subscript out of range", if there is no delimiter in between at all, thus no second part at all.