I'm creating an Excel file using vb.NET but I have the following problem/situation:
I want to add a formula to my cells on specific row and on specific starting position, for example: from F5 to Z5. The main problem is that I need to do two formulas the first one ONLY on the first cell (F5 for example) and from F5 to Z5 another formula. The other problem is for example, I have data from A1 to Z5 then I insert a blank row and then I have data from A7 to Z7.
At the moment I have a code which allows me to move from cell F5 to Z5 one cell per one cell but only insert data (formula) on F5 and G5 because I don't know how to handle the range without letters. This is an example of my code:
'' LastLetter is equal to the index o Z Column (I always know which is the last column letter.)
For workingOnCell As Integer = 7 To lastCellLetter Step 1
If itsFirtsCell = 1 Then
Dim select As Excel.Range = CType(SW.Cells(5, workingOnCell), Excel.Range)
'' Formula only for first cell
select.Value = "=F2+F3+F4"
itsFirtsCell = 0
Else
Dim select As Excel.Range = CType(SW.Cells(5, workingOnCell), Excel.Range)
'' Formula for all the rest of cells
'' Problem starts here because formula for second cell it's ok but for the third cell should be =G5-H2-H3-H4 and here is where I don't know how to handle cell letters
select.Value = "=F5-G2-G3-G4"
End If
Next
Other problem with above code is that if I have data on A7:Z7 range I should do the same thing but my code only going to work with F5:Z5.
How can I make my code works as expected or how can I solved it?
Related
I have this formula:
IF(ROWS($Q$27:Q27)<=$P$25,INDEX(DataTable[[#All],[Time]],$P27),"")
and if I drag it to the right, it should automatically read each column respectively; example:
=IF(ROWS($Q$27:R27)<=$P$25,INDEX(DataTable[[#All],[Name]],$P27),"")
^Notice that the first Q27 is fixed, the second Q27 is variable.
I drag this formula to the right by 15 columns, and down to 50 rows. that's 750 formulas in total.
I want to do this in vba, but if I did this, it will be 750 lines of code for each cell representing each row/column.
example: .Range("G17").Formula=IF(ROWS($Q$27:R27)<=$P$25,INDEX(DataTable[[#All],[Name]],$P27),"""")
and if I drag it down, it will automatically pick up what I exactly want, example:
=IF(ROWS($Q$27:Q28)<=$P$25,INDEX(DataTable[[#All],[Time]],$P28),"")
so this formula should be written 750 times in total for the cell range [ A27:N76 ]
Any faster / more dynamic approach? and if possible, can I make it depend on more than 50 lines based on a cell value inside the sheet?
Example:
This should do it all in one line:
Range("A27:N76").FormulaR1C1 = "=IF(ROWS(R27C17:RC[16])<=R25C16,INDEX((DataTable[[#All],[Name]],RC16),"""")"
EDIT: Seems a more that one line of code required after all 😊
The code below will do what you want (this time fully tested)
Sub FillFormulas()
Dim inC%, rgHead As Range
''' Assumes the target sheet is Active.
''' o If that's not the case, change this With statement to reference the target sheet
With ActiveSheet
''' Set rgHead to the Table's header row
Set rgHead = .ListObjects("DataTable").Range.Rows(1)
''' Add the formulas to the target range, column by column updating the table header on the fly
With .Range("A27:N76")
For inC = 1 To .Columns.Count
.Columns(inC).FormulaR1C1 = _
"=IF(ROWS(R27C17:RC[16])<=R25C16,INDEX(DataTable[[#All],[" & rgHead.Cells(inC) & "]],RC16),"""")"
Next inC
End With
End With
End Sub
so this formula should be written 750 times in total for the cell range [A27:N76]
You don't need to do that. If you specify range.Formula, it will fill the proper formulas all the way across and down. Just give it the formula of the top/left most cell.
So, in your case
Range("A27:N76").Formula = "=IF(ROWS($Q$27:R27)<=$P$25 ... "
EDIT: This response had some obvious errors
This has an obvious error (as tested part and then merged to the full thing).
Range(A27:N76).FormulaR1C1 = "=IF(ROWS(R27C17:RC[16])<=R25C16,INDEX((DataTable[[#All],[Name]],$P27),"""")"
I have the feeling that my previous question is being misunderstood. Therefore, I will do this as follows. What I would like is the following:
In this picture you see that the input is 4 in cell B1. This B1 cell is used as an input for a complicated model in a different sheet. The output of that model is linked to B2. I do not want to modify the complicated model on the other sheet (this part is required).
Now I would like to create a table like this:
So when the input is 4, the output from the model in the other sheet is 1. Now I can do this manually for 1, 2 and 3, by simply replacing the number written at B2 (which is 4) to 1 and check its output. Let’s observe what our complicated model gives us:
Apparently it gives us a 9, so I fill 9 in the F2. Now this is currently not a problem, since my table goes from 1 to 4. But how do I automate this? For example if I go from 1 to 100.
The problem is, you cannot touch or simplify the model on the other sheet.
How would one do this in VBA or do this in Excel itself?
I think you might have an issue in your explanation. Your example is A1 = 1, B1 = A1+5, despite saying it's A1 & A2. You are saying "Columns C & D" when I believe you mean "Rows 3 & 4).
If I understand your plight correctly, you are looking to drag down (auto-fill) the formula to the subsequent rows. You can do this with VBA, but you can do it without.
Provided you have data in the first column (A) as far as you would like the formula to travel, you can double-click from the lower right hand corner of the formula-reference cell and it will fill down. You could also drag the formula down by clicking and holding the lower right hand corner of the formula-reference cell.
You will know if you have the lower right hand corner if your cursor changes from from a "+" that is relatively large (with interior color) to a "+" that is relatively small (with no interior color... all black).
You will need to ensure that you have relative references when doing this, or ensure that your non-relative references are what you want. This is more than your question asked, but is important when doing this type of work.
See this:
Range("B1").Formula = A1 + 5
In this formula, A1 is relative to B1 by an off-set of -1 column. Every cell that the formula is pasted or dragged into will perform the formula with the cell that is -1 column relative.
You can add specifics to columns, rows, or cells, by use of "$". Say you have your example, and want to show the formula in Column C. There're 3 scenarios by using "$" which have different outcomes:
Fully relative, the dragged-formula will automatically designate the adjacent column.
Range("B1").Formula = A1 + 5
Range("C1").Formula = B1 + 5
Range("B2").Formula = A2 + 5
Range("C2").Formula = B2 + 5
If the "$" is in front of the column in the formula, the-dragged will "lock" the column, so when the formula is dragged, the column stays the same, but the row number will change.
Range("B1").Formula = $A1 + 5
Range("C1").Formula = $A1 + 5
Range("B2").Formula = $A2 + 5
Range("C2").Formula = $A2 + 5
If the "$" is in front of the row in the formula, the-dragged will "lock" the row, so when the formula is dragged, the row stays the same, but the column will change.
Range("B1").Formula = A$1 + 5
Range("C1").Formula = B$1 + 5
Range("B2").Formula = A$1 + 5
Range("C2").Formula = B$1 + 5
If the "$" is in front of the each the column and row in the formula, the-dragged will "lock" both. When the formula is dragged, the referenced-cell stays the same.
Range("B1").Formula = $A$1 + 5
Range("C1").Formula = $A$1 + 5
Range("B2").Formula = $A$1 + 5
Range("C2").Formula = $A$1 + 5
Hopefully that helps and is what you're looking for!
So you want to automate putting values through your model and recording the outputs.
A very simple approach begins with putting your list of inputs in column E as in your example picture. Note down the start and end row numbers - 2 and 5 in your example (as your input values are in the range E2:E5).
In the VBA editor created a new sub in a new module to hold your code (you can Google how to do this). The code is fairly simple.
Sub TurnInputsIntoOutputs()
' First we create some useful and important variables
Dim inputStartRow As Long ' The row your input values start on
Dim inputEndRow As Long ' The row your input values end on
Dim currentRow As Long ' A placeholder for when we cycle through the rows
Dim processingWorksheet As Worksheet ' How we're going to reference your worksheet
' Then we put values into those variables
inputStartRow = 2
inputEndRow = 5
Set processingWorksheet = ThisWorkbook.Sheets("*the name of your worksheet here*")
' Now we cycle through the input rows
For currentRow = inputStartRow to inputEndRow
' Put input value from the current row of column E into cell B1
processingWorksheet.Range("B1").Value = processingWorksheet.Range("E" & currentRow).Value
' Put the resulting output value into the current row of column F
processingWorksheet.Range("F" & currentRow).Value = processingWorksheet.Range("B2").Value
Next currentRow
End Sub
And then just run your macro (you can link it to a Form button or just run it from the VBE - easy enough for your to Google how to do).
I'm trying to do a formula where it is CELL / 127.05 - 1 and apply this to columns H-Y and rows 2-455. I'm not really familiar with excel and am going about this calculation cell by cell. Also, I'm running into a "circular" problem where certain cells rely on another, if anyone could explain this.
Thanks ahead of time!
A formula in a cell generally cannot refer to itself. If you want to apply an operation to an existing range of data, you can, but it is quite rare and surely not in the spirit of a spreadsheet app.
Regarding your question, you could
- enter a value (127.05) anywhere in an empty cell,
- then copy that cell
- then select the range you want to modify
- then select Paste Special / Divide (or any other operation)
As I said above, it sounds like you want to apply that formula to same cell that contains the value you want to act on. That will not work. results cells (i.e. containing your conclusions) will contain the formula and a reference to the cell it will act on. (Although I am using a smaller area for illustration, the principles will apply to your specific application)
Note - I used the randbetween(min,max) function to populate all the data cells. this is why each image contains different data. You of course will use cells containing static data.
For a simple example:
Say you put the value 127.05 in cell A1, and have a range of data cells, like this:
In cell F1, enter = b1/$a$1 - 1 like this:
Note, the $ signs tell Excel to use a static location cell reference. After hitting enter, the value -0.85045 will appear. Now, click and hold your mouse starting in that cell, and drag your mouse down to row 14 release the mouse button and hit keys <ctrl><d>. Your sheet should look like this:
Hold down the shift key while the column is still selected, and hit the right arrow key 3 times, Your sheet should look like this:
release the shift key and while the cells are all highlighted, hit keys <ctrl><r>. The results are here:
One way is to highlight the column (or specific range) you want to apply the formula to, press F2 to access the formula bar, type the formula, and press CTRL+D to paste DOWN if the range is vertical and CTRL+R to paste ACROSS if the range is horizontal. Say that your data looks like this:
A B
--- ---
5 A1/127-1
4
7
8
Then in order to copy the formula down, highlight A2 to A4 and press CTRL+D, or highlight B1, and click on the bottom right of the box that comes up surrounding the cell.
If you wanted to simply replace the values in A with their formula values you would still have to use Column B as a 'helper' column, rather than entering the value right into the cell. This is in fact exactly what is giving you the circular reference error.
Regarding the circular error, you may be trying to apply the formula to the cell you are already in. For example, if you are trying to apply the formula A1 / 127 - 1 in the cell A1 Excel won't know what to do because you have specified that the value of A1 is both the value in the specified cell and another value ( A1 / 127 - 1), which can't be true.
Now, the only way I know of to do what you're requesting is with VBA, because I realized just now that I asked a very similar question a while ago which was helpfully answered by Gary. The code was as follows:
Sub Formulate()
Dim N As Long, i As Long, dq As String
N = Cells(Rows.Count, "A").End(xlUp).Row
dq = Chr(34)
For i = 1 To N
v = Cells(i, 1).Value
Cells(i, 1).Formula = "=Text(" & v & "," & dq & "mm/dd/yyyy" & dq & ")"
Next i
End Sub
I have an Excel spreadsheet that I am writing out to a file. I am currently using the following method to reproduce the contents of each cell:
cell_contents = Right(Space(10) & Trim(Cells(iRow, iColumn)), 10)
However, if the contents of the cell are longer than 10 characters long (or however long I choose to specify), then I loose parts of the data. Is there a way to quickly and easily get the length of the longest string in a range of cells?
I have seen people suggest using the following loop, but I was hoping that I might be able to do it without having to loop over all the cells:
For Each c In SourceRange.Cells
if len(c) > b then b = len(c)
Next c
Record these steps as a macro in the cell you want to calculate the max length.
1) enter this formula
=MAX(LEN(A1:A4), 1) -- Edit for your range.
2) press control-shift enter (FormulaArray)
3) now stop recording macro
4) view the VBA. copy what you need to your VBA.
Should give you something like this:
Selection.FormulaArray = "=MAX(LEN(R[-10]C[1]:R[-1]C[1]))"
Press Alt-F11, insert new module, paste code bellow.
Public Function maxRangeLength(data As Range) As Integer
Dim ret As Integer
ret = 0
For Each cell In data
ret = Application.Max(ret, Len(cell))
Next cell
maxRangeLength = ret
End Function
Usage:
=maxRangeLength(A8:D11)
Could just use ... {=MAX(LEN(A2:A200))}
In the top cell put =MAX(LEN(A2:A200)) .. and then press CTRL-SHIFT-ENTER to get the curly braces.
Suppose that the data is in column A and there is a heading row for your spreadsheet.
Create a new column next to it and enter in the formula: =LEN(A2)
Autofill down that formula.
Turn on filtering for that column and the click the drop-down box on the column heading cell.
Scroll down to the bottom of the list where the largest summarized value is.
That will be the largest value in the column.
After 3 hours of searching I still didn't find an answer, here is what I am trying to do:
I am trying to fill with green any row that has WBS in it and with Red any row that has ACT in it and Blue any row that has EPR in it. It works for the first formula then when I try to add the second one every thing get messed up.
what i have understood is that you need to search a keyword in a row and if its found in any cell of that row then color it.
May be we can do it with conditional formatting but i have another idea. We can create a simple search function in Excel VBA. Something like this:
=search_row(A1:F1,"EPR")
The function will return 1 if EPR is found in any cell of specified row. Now if you create two different columns at the end of data columns, name first with WPS and second with EPR and write this function in it. Like
G1 =search_row(A1:F1,"WPS")
H1 =search_row(A1:F1,"EPR")
Drag it to end. Now sort the columns. First for WPS from higher to lower. Then color all rows having 1 in a single select. Similarly do the same with EPR (H1) column.
To use this function you can download the macro file from the following URL:
http://asimishaq.com/myfiles/SearchHighlight.xlsm
Now to run it first of all enable macros, and then re-open your data file and then open this macro file. As long as this macro file is opened you can use this function. Following is the VBA code if you want to create the macro yourself:
Function search_row(sRow As Range, Keyword As String)
Dim i As Integer
Dim Found As Integer
For i = 1 To sRow.Columns.Count
If InStr(1, LCase(sRow.Cells(1, i)), LCase(Keyword)) > 0 Then
search_row = 1
End If
Next
End Function
I had a go at making a function similar to asim-ishaq to determine if your search term exists in the row for fun :) then tried to apply it to highlighting rows, turns out I dont know how to use conditional formatting very well! Figured it out in the end, hopefully I've explained it well enough.
With this you will have to have (one) extra column at the end of your data to contain the result.
It might be possible to not require the extra column by putting the function inside the conditional formatting, however I couldn't get it to work (didn't try very hard). This isn't a great loss as it's much simpler to edit the formula if its on the workbook, instead of having to go through each conditional rule to edit it, should you need to edit it in the future.
To get the formatting to work you will need to create a number of rules (one per keyword)
You want to create a rule of the type shown below, in the formula box you need something along the lines of: =INDIRECT("D" & ROW())=0 where D is the column containing the result of the function below and 0 is the index of the keyword you're highlighting.
In my example, the formula in the D Column is: =SearchRow(An:Cn,"ABS","KBS","JBS") (where n is the row the formula is on)
Set the formatting as desired then press OK, when you return to the rule manager you will need to update the Applies to value, which should be a range that covers all the data you want to highlight. In my example it was $A$1:$C$3
My function below takes 2+ Arguments, The first is the range to search. The second (and any subsequent ones) are search terms.
The function will return a number. -1 for no matches and 0+ for the found search term. The number depends on the position in the arguments.
A1 = "ABS"
B1 = "SBA"
A2 = "SBA"
B2 = "ABS"
A3 = ""
B3 = ""
C1 = "=SearchRow(A1:B1, "ABS", "SBA")"
C2 = "=SearchRow(A2:B2, "ABS", "SBA")"
C3 = "=SearchRow(A3:B3, "ABS", "SBA")"
C1 > 0
C2 > 1
C3 > -1
The function will always return the first result, searching left to right comparing each cell to the Keywords in order. Using my example, if a cell contained "SBA ABS" the result would be 0 (for ABS). I guess your cells will probably only contain one keyword though so this shouldn't be a problem?
Public Function SearchRow(ByVal Row As Range, ParamArray Keyword() As Variant) As Integer
Dim Column As Integer
Dim Value As String
Dim Index As Integer
Dim Result As Integer
For Column = 1 To Row.Columns.Count
Value = LCase(Row.Cells(1, Column))
Result = -1
For Index = LBound(Keyword) To UBound(Keyword)
If InStr(1, Value, LCase(Keyword(Index))) > 0 Then
Result = Index
Exit For
End If
Next Index
If Result > -1 Then
Exit For
End If
Next Column
SearchRow = Result
End Function