How do I write VBA script so that it will compare data? - excel

We need a script to compare the dates in column D to the dates in column E.
If the date in column D is two days before the date in column E then we need column F to state that in the corresponding row to D. We have a range of 2 days before and 2 days after (shoulder days). We need to be able to easily reproduce this and have it be able to run when we import it into access. we have roughly 3300 unique days to check.
I have tried using datevalue or a formula but we need to be able to reproduce this in the future and the formula doesn't allow us to easily do that.

I will not provide a complete implementation, but I can show you the way how you can do it (either the Excel formula way or with VBA code). Both ways will automatically calculate the values you need so you can easily import it into Microsoft Access - the import will take the calculated values from the cells you've selected.
The first way, which is also the simplest way, is to do that with simple Excel formula, consider this picture showing how the formula will calculate the values in columns F and G:
(Note: It is showing German date format, but you can easily change that in Excel).
In column G it calculates the difference D2 - D1 and displays it in days.
Then, in column F there is a simple if condition to determine if the date D1 is less, greater or equal than D2. The Result is calculated automatically.
The formula in row 2 are:
Hint: You can drag and drop the formula to the rows 3 - n below, so you can create a lot of rows prefilled with that formula.
A second way is that you can write a VBA function for the (simple) calculation formula in column F:
Function CalcResult(D1 As Variant, D2 As Variant) As Variant
CalcResult = ""
Dim result As String
Dim diff As Single
diff = D2 - D1
If (diff > 0) Then
result = "D1 < D2"
ElseIf (diff = 0) Then
result = "D1 = D2"
ElseIf (diff < 0) Then
result = "D1 > D2"
End If
CalcResult = result
End Function
This needs to be entered in the VBA editor, which you can display if you press Alt+F11. After you have done that, press Alt+F11 again to close VBA and return to your Excel sheet.
Then, place the formula =CalcResult(E2; D2) in cell F2 as shown below:
Like in the previous example, you can drag & drop the formula to the rows 3 - n below, so you can create a lot of rows prefilled with that formula.
The advantage of the 2nd approach is that you can refine the function CalcResult later without having to change the cells again (as it is the case in the first example).
Note: The function above needs to be in a separate module and you need to save the workbook as "Macro enabled workbook" later - otherwise you'll lose the VBA code.
A third way is to use the Excel macro recorder and record whatever you intend to do. It will create a public module with VBA code. If the recorder asks you, choose to store the code in the workbook.
Later you re-visit the generated VBA code and refine it - for example, put a for loop around it to automate things you've recorded once.
This approach is good for creating a "Calculate" button and put some logic behind it.

Related

combine all cells, numbers and symbols to a sum

Good day,
I'm at a loss on this problem.
I have a group of cells that contain words, like apple, this word would be the value. It is separated by a symbol for completing the math. They can be changed by the user to make custom calculations.
Cell A1 is "apple", B1 is "+", cell C1 is "apple", cell D1 is "*", cell E1 is "apple", call F1 is "=" and cell G1 is the suggested total, in this case would be "6".
It would be posted as | apple | + | apple | * | apple | = | 6 |
The legend holds the value for the word, so if you enter 2 in the legend, apple would be 2.
The logic would determine that the formula would be 2+2*2= if written in excel, I would like to combine all the cells and calculate this.
I tried using =sum, sumproduct, concate and the like to no avail.
Any head way I did make, I ended up getting BEDMAS wrong as it calculated it as 2+2=4*2=8, instead of the correct 2*2=4+2=6.
Anyone know of a way to combine these cells and properly sum the values to the correct total?
Thank you for your time!
Go to the Name manager and create named range Eval, into Refers to field add formula:
=EVALUATE(CONCATENATE(VLOOKUP(Sheet1!A1,Sheet1!$A$3:$B$5,2,0),Sheet1!B1,VLOOKUP(Sheet1!C1,Sheet1!$A$3:$B$5,2,0),Sheet1!D1,VLOOKUP(Sheet1!E1,Sheet1!$A$3:$B$5,2,0)))
In range A3:B5 I have legend.
Change references as you need. Then in cell G1 write formula =Eval.
Sample:
This is a UDF based solution. Its advantage is that it's more versatile and by far easier to maintain if you learn its elements of code. The disadvantage is in that you do have to learn the elements of code and you have an xlsm macro-enabled workbook which isn't welcome everywhere.
The setup is simple. I created a table with columns Item and Value. I placed it on another sheet than the task. In fact, you could make the sheet with the table VeryHidden so that the user can't look at it without access to the VBA project, which you can password protect. I called the table Legend. The item columns has names like apple, pear, orange. The Value column has the numeric values associated with each name.
Note that, since this is a VBA project, the entire list can be transferred to VBA leaving no trace on the sheet. You could have a function to display the value of each item as the user clicks on it and have it disappear as he clicks elsewhere.
Next I created a data validation drop-down in A1 with the List defined as =INDIRECT("Legend[Item]"). Copy this cell to C1 and E1.
Then I created another Data Validation drop-down in B1 with the list as +,-,*,/. This drop-down must be copied to D1.
Now the code below goes into a standard code module. Find the way to create it because it isn't any of those Excel sets up automatically. It's default name would be Module1. Paste the code there.
Function Evalue(Definition As Range) As Double
Dim Task As String
Dim Fact(2) As Double
Dim C As Long
Dim i As Long
With Definition
For C = 1 To 5 Step 2
On Error Resume Next
Fact(i) = Application.VLookup(.Cells(C).Value, Range("Legend"), 2, False)
i = i + 1
Next C
Task = "(" & Fact(0) & .Cells(2).Value _
& Fact(1) & ")" & .Cells(4).Value _
& Fact(2)
End With
Evalue = Evaluate(Task)
End Function
Now you are ready for testing. Call the function from the worksheet with a call like
=Evalue(A1:E1). You can use it in comparisons like =IF(G6 = Evalue(A1:E1), "Baravo!", "Try again"). As you change any of the components the cell with the function will change.
Remember to use absolute addressing if you copy formulas containing the range. If you need to get a result in VBA while testing, use this sub to call the function.
Private Sub TestEvalue()
Debug.Print Evalue(Range("A1:E1"))
End Sub
My Sheet
Here is what I have.
In cells M - U, i count all the instances of the word from cells E, G and I from the legend.
=SUMPRODUCT((LEN(E3)-LEN(SUBSTITUTE(E3,$B$3,"")))/LEN($B$3))
In cells W - AE, I multiply the instances with the value to give me a total each time the word appears.
=SUM(M3*$C$3)
In cell E8 - I8, i add the three possible values together.
=SUM(W3:Y3) so each worded cell is now a number.
I'd like to take the cells E8 - I8 to make a calculation in k8 and so on.
So, each cell is put together to make an
=SUM(E8:I8)
statement, which all works except E11 - I11 which equates to 26 instead of 43.

How to set up Excel VBA Loop for vlookup

I have a dashboard (image below) where I manually add entries. Then there is a log (image below) where all entries are recorded with the help of IF and Vlookup functions.
I need a code so so that every output cell in the log finds through all the entries in the dashboard and gives the answer. I think loop for vlookup will be used.
[Edit]
Consider the Dasboard table as a discrete table where manually entries are posted.
Consider log table as a continues table where record of every hour for each date is kept. The entries from Dashboard table get posted to the log table. New Image attached New Image
I have entered this function in output column in the log table:
=IF( AND(H3=$B$3,I3>= $C$3,I3<$D$3) ,$E$3,0) + IF(AND(H3=$B$4,I3>=
$C$4,I3<$D$4) ,$E$4,0) + IF (AND(H3=$B$5,I3>= $C$5,I3<$D$5), $E$5,0)
This works fine for me for plotting the entries but the problem is for every row in the dashboard i have to add a new IF-And function in the above. so for example if i want to add the 4th row of dashboard to be sync with the log ill have to add
+If(AND(H3=$B$6,I3>=$C$6,I3<$D$6),$E$6,0)
I want every row in the dashboard to add automatically somehow with a loop like:
i = variable
= If (AND(H3=$B$i,I3>= $C$i,I3<$D$i), $E$i,0)
Only one i will be greater than 0 while the rest will be zero. so the function should return me the sum of all i rather than just the last iteration.
Maybe just filldown the formula manually? if insist with macro, something like
Sub test()
Range("K3").Value = "X"
Range("K3:K10").FillDown
End Sub
replace "X" with your formula, keep the " "
replace K10 with how far down you want
----edit----
let me break down below for you,
match(H3,B:B,0), will find the correct row in B that = H, in H3 case it finds B3
INDEX(B:E,MATCH(H3,B:B,0),2) -> now it find B3, index let you find C3 (notice the 2,3,4 in later codes, it means the column from B3)
and (I3>=...,J3>=...)now we got both start and end time, we use I and J to compare
if 3. is true, lookup the output column, else 0
=IF(AND(I3>=INDEX(B:E,MATCH(H3,B:B,0),2),J3>=INDEX(B:E,MATCH(H3,B:B,0),3)),INDEX(B:E,MATCH(H3,B:B,0),4),0)

Excel 2013 color fill when number changes in a column

I'm working on data-analysis where i would like to be able to automatize color fill when looking through large amount of data where there are abundant amount of ghost logs and taking too much of my time as they are severely irrelevant.
So what i would like to do in Excel, is to be able to color fill a cell when the number changes in a column marking a different set of logs.
For instance if there are six rows of log number 456455, i would like the code to color fill the first cell when the number changes to 456456 so that it helps me identify logs faster when i know where the sets are starting. I'm kind of a newbie when it comes to Excel but this loop would help me a lot!
Thx for your time
This can be done with conditional formatting. Use a rule that compares the current cell with the cell in the row above and format if the two are different. Note that you will need to use relative references without $ signs. In the screenshot below, the conditional format is applied from row 2 to 19 and in row 2 the formula compares A2 with A1, in the next row it compares A3 with A2, and so on. If the two cells are different, the cell will change colour.
If you have some knowledge in VBA, you can implement a macro that looks at the column where you have your log number and if the value changes from one cell to another, then you highlight this cell.
I attached a template of code that works for this task.
Sub highlightChange()
Dim preVal As Integer
preVal = 0
For Each o In Range("A:A")
'Go through column
If o.Value <> preVal Then
o.Interior.Color = vbRed 'Color the selection
End If
preVal = o.Value
Next o
End Sub
There may be other solution without VBA, however, it is quite easy and practical to use a macro.

Calculate Excel formulas in VBA but display only the value in Excel

This is my first post and I can't find an exact answer anywhere. I have an Excel spreadsheet that is becoming too large to operate because I have long formulas in millions of cells. I need to know how to calculate the formula using VBA but have only the value appear in Excel. An example is I want to multiply column B by column C:
I have tried this code:
Range("D3:D6").Formula = Evaluate("=B3*C3")
It correctly calculates for the first cell, but for the other cells it still tries to calculate B3*C3 as a fixed reference rather than as a dynamic references that changes as the cell position changes.
How could I fix this? Thankyou.
Edit:
My actual spreadsheet looks like this:
This formula needs to be applied down 17520 rows and across 300 columns, but I only want the values to appear in Excel. The purpose of this is to reduce file size and reduce calculation time.
=IF(-SUMIF(AIG$4:AIG4,"<0")>0.9*SUMIF(AIG$4:AIG4,">0"),0,IF(-SUMIF(AIG$4:AIG4,"<0")-IF(WQ5<'Battery Specs'!$B$13,-'Battery Specs'!$B$15,IF(WQ5=ROUNDDOWN('Battery Specs'!$B$13,0)+1,-('Battery Specs'!$B$13-ROUNDDOWN('Battery Specs'!$B$13,0))*'Battery Specs'!$B$15,0))>0.9*SUMIF(AIG$4:AIG4,">0"),-(0.9*SUMIF(AIG$4:AIG4,">0")+SUMIF(AIG$4:AIG4,"<0")),IF(WQ5<'Battery Specs'!$B$13,-'Battery Specs'!$B$15,IF(WQ5=ROUNDDOWN('Battery Specs'!$B$13,0)+1,-('Battery Specs'!$B$13-ROUNDDOWN('Battery Specs'!$B$13,0))*'Battery Specs'!$B$15,IF((0.9*SUMIF(AIG$4:AIG4,">0")+SUMIF(AIG$4:AIG4,"<0"))>'Battery Specs'!$B$10,0,IF(((0.9*SUMIF(AIG$4:AIG4,">0")+SUMIF(AIG$4:AIG4,"<0"))+$AIF5*0.9)>'Battery Specs'!$B$10,'Battery Specs'!$B$10-(0.9*SUMIF(AIG$4:AIG4,">0")+SUMIF(AIG$4:AIG4,"<0")),$AIF5))))))
Try
Range("D3:D6").Formula = "=B3*C3"
Range("D3:D6").Value = Range("D3:D6").Value
or simply
Range("D3:D6").Formula = Evaluate("(B3:B6)*(C3:C6)")
Using Evaluate to calculate the formulas and then transfer the values to Excel will be slower than having Excel calculate the formulas directly.
Here are a couple of things you could try:
a) Formulas
You only have 5 million formulas in 5 million cells - this is not an overwhelmingly large number but your formulas are very long and each formula references a large number of cells.
Your formula contains many repeated expressions and calculations - move them out to helper cells and try to simplify/shorten your formula.
b) VBA - don't use Evaluate - just grab the range of 5 million cells into a single variant array and use VBA Loops, arithmetic and logic to accomplish the same task as your formulas and then put the array back.
I believe best option is to keep formulas instead of using VBA to produce same formulas. Instead, when entering new data in SpreadSheet, be sure to set calculations to manual (go to Formulas tab=>Calculation Options=>Manual. This way you wont trigger calculations when entering/pasting new values, meaning your Excel file will operate just as fast as if there was no formulas. After you entered/pasted all new values, set Calculations to Automatic.
You might want to try this:
Dim i as Integer
For i = 3 to 6
Range("D" & i).Value = Range("B" & i).Value * Range("C" & i).Value
Next i
The other alternative is to name your formula, for instance, instead of saying =B3*C3, you can give it a name say times value, and then say =timesvalue. Next, remove the formula and leave the value only. E.g. range("D3:D30").value=range("D3:D30").value

vba code to change column formula by dynamic dragging

i need to write vba code wherein cell GQ4 has formula
ActiveCell.Formula = "=SUM(CO4:CQ4)"
Now there is new month added every month in excel data hence the formula will also change dynamically every month.
ie next month it will be
"=SUM(CP4:CR4)"
in short it is dragging its column selection by 1 column
Please help me write a vba code that will dynamically change the formula.
Note sure if it is possible to return a formula from a custom function, but a solution might be to write a custom function that returns the range you want, and then have the formula in GQ4 take the range as an argument.
Or you can solve it with a normal worksheet formula.
=SUM(INDIRECT(ADDRESS(4;15));INDIRECT(ADDRESS(4;16));INDIRECT(ADDRESS(4;17)))
Replace the column numbers with a base + offset that you can get by using a date function. E.g.
=SUM(INDIRECT(ADDRESS(4;14 + =MONTH(TODAY())));INDIRECT(ADDRESS(4;15 + =MONTH(TODAY())));INDIRECT(ADDRESS(4;16 + =MONTH(TODAY()))))

Resources