Thanks for taking a look at my question. Know that I am new to stackoverflow and VBA I have a long macro I've been working on. At one point in the macro I have to convert "Start Depth" (L) and "End Depth" (M) from "m" to "ft". Then I subtract the two to find the "Footage" (N). However, some of the values in the columns are originally left blank. So, after making my conversions and subtractions, I'm left with "#VALUE!" which is giving me errors later on in the macro. Originally I had changed all of the blanks to 0's before the conversions and subtractions. But, After "finishing" the macro I realize the zeros are messing with presenting the data. So, I'd like to just do the conversions and subtractions and then, change all the "#VALUES!" back to blanks. I found some stuff on this but nothing that I could (that i know of) use or specific to me:
http://www.ozgrid.com/forum/showthread.php?t=60740 and https://superuser.com/questions/715744/excel-2010-formula-how-do-i-write-this-formula-vba
Here is what i was using to change blanks into 0's
Worksheet1.Select
lastrow = Range("A666666").End(xlUp).Row
For Each cell In Range("A1:Q" & lastrow)
If Len(cell.Value) = 0 Then
cell.Value = 0
End If
Next
Here is the code resulting in errors. Note: The data starts with blanks and after using these formulas I am given errors because some of the original cells begin as null or blanks. Also, These lines aren't in this order but, they are the lines leaving errors.
ActiveCell.FormulaR1C1 = "=CONVERT(RC[2],""m"",""ft"")"
Selection.AutoFill Destination:=Range("N2:O2"), Type:=xlFillDefault
Selection.AutoFill Destination:=Range("N2:O" & lastrow)
Range("N1") = "Footage"
Range("N2").Select
ActiveCell.FormulaR1C1 = "=RC[-1]-RC[-2]"
Selection.AutoFill Destination:=Range("N2:N" & lastrow)
Any help is appreciated. Thanks guys!
It depends if the #VALUE! is being generated from a formula or from VBA code.
Formula
If it's being generated from a formula, wrap the formula in the IFERROR function. This was added in Excel 2007 I believe. So for example if your formula was:
=A1-B1
Then you could put
=IFERROR(A1-B1,"")
Which is saying, if A1-B1 is an error, return "", otherwise return the result of A1-B1.
VBA
If the value is being generated by VBA you could write a helper function that works like IFERROR
Public Function MyIfError(value As Variant, value_if_error As Variant)
If IsError(value) Then
MyIfError = value_if_error
Else
MyIfError = value
End If
End Function
And then pass your value through that.
This does not directly answer your question, but it does fix the presentation of Zero's on your worksheet. You can use the following setting to show Zeros as Blanks through VBA: ActiveWindow.DisplayZeros = False It might be a consideration instead of looping through everything looking for 0's and switching them to blanks manually.
Worksheet1.Select
lastrow = Range("A666666").End(xlUp).Row
For Each cell In Range("A1:Q" & lastrow)
If Len(cell.Value) = 0 Then
cell.Value = 0
End If
Next
For Each cell In Range("A1:Q" & lastrow)
cell.value = WorksheetFunction.Iferror(cell.value,"")
End If
Next
I'm sorry I don't have opprtunity to test it right but give it a try.
Bottom line is that I simply included a second loop that runs IFERROR function on your data.
Related
I am looking to delete everything that does not match my inputbox value. However, it seems like the loop I am using is not working at all! It seems the code does not read the loop. The loop should delete the entire row of each cell in the column E that does not match my inputbox variable. I run the code, insert the value in the input box and nothing gets deleted.
Can someone PLEASE help me??
'Get the Tenrox code to be deleted
tenroxcode = InputBox("Insert the Tenrox Code that you want to keep")
'Find and delete all unnecessary tenrox codes
r = Application.Match(tenroxcode, Columns("E"), 0)
Do While IsError(r)
Rows(r).EntireRow.Delete
r = Application.Match(tenroxcode, Columns("E"), 0)
Loop
Try this:
tenroxcode = InputBox("Insert the Tenrox Code that you want to keep")
With Worksheets("Sheet1") ' change as needed
With .UsedRange.Columns(5) 'assumes data is in column a1 and contiguous across cells
If Not .Find(tenroxcode, lookat:=xlWhole) is Nothing Then
.AutoFilter 1, "<>" & tenroxcode
.offset(1).specialcells(xlCellTypeVisible).entirerow.delete 'offset so header row stays
End If
End With
.AutoFilterMode = False
End With
A simple way to do this is to use the Autofilter to filter on anything that doesn't match your condition, and then delete the rows. And I'd suggest turning your data into an Excel Table first, because it simplifies code.
Simply fire up the macro recorder, and you'll get code like this::
ActiveSheet.ListObjects("Table1").Range.AutoFilter Field:=1, Criteria1:= _
"<>SomeValue", Operator:=xlAnd
Range("Table1[Column1]").Select
Selection.EntireRow.Delete
ActiveSheet.ListObjects("Table1").Range.AutoFilter Field:=1
That should be enough to get you started.
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 pretty unfamiliar with VBA, and I am stuck with this portion of my code. I have a cell with a vlookup equation in it I'd like to use as a parameter to find a value in a table on a different sheet and copy the entire row over to a different sheet. I've used this code in the past to copy data over based on a single parameter, but I think the problem I'm running into is that the cell I'm trying to reference contains a vlookup equation in it.
Sub Test()
For Each cell In Sheets(RawDataLoader).Range("E:E")
If cell.Value = "B8" Then
matchRow = cell.Row
Rows(matchRow & ":" & matchRow).Select
Selection.Copy
Sheets("Dashboard").Select
ActiveSheet.Rows(matchRow).Select
ActiveSheet.Paste
Sheets("RawDataLoader").Select
End If
Next
End Sub
RawDataLoader is the sheet with my table
Dashboard is the sheet where I want the cells to go
B8 is the cell on the sheet Dashboard I want to use as the value the table looks up.
The range with the values I want it to search through is E:E and on the RawDataLoader sheet.
I know that the cell.value portion of my code is incorrect, I just do not know how to reference a cell value, so I put the cell I wanted to reference.
Thank you!
You just need to use Sheets("Dashboard").Range("B8").value instead of "B8". You can also simplify your code; avoid using Select and loop only on the used range instead of the full column.
Sub Test()
Dim cell as Range
For Each cell In Intersect(Sheets("RawDataLoader").UsedRange, Sheets("RawDataLoader").Range("E:E"))
If cell.Value = Sheets("Dashboard").Range("B8").value Then
cell.EntireRow.copy Sheets("Dashboard").Rows(cell.Row)
End If
Next
End Sub
I am trying to rank values using column J and tie breaker in column K with the result populating in column N. Column J & K are values.
Somehow it only generates one value wherever my cell is pointed at, which means if I run the vba codes at cell C19, it will just populate value 1 in C19, not from N6 where I want the results to be.
Here are my codes,
Sub test()
Dim LR1 As Long
LR1 = Range("J" & Rows.Count).End(xlUp).Row
With Range("N6:N" & LR1)
ActiveCell.FormulaR1C1 = "=1+SUMPRODUCT(--(R6C10:R33C10<RC[-4]))+SUMPRODUCT(--(R6C11:R33C11<RC[-3]),--(R6C10:R33C10=RC[-4]))"
End With
End Sub
I am not sure what went wrong. I tried to do it manually using the excel formula and its working fine but not my vba codes.
ActiveCell is your issue.
Change
ActiveCell.FormulaR1C1 = "=1+SUMPRODUCT(--(R6C10:R33C10<RC[-4]))+SUMPRODUCT(--(R6C11:R33C11<RC[-3]),--(R6C10:R33C10=RC[-4]))"
To .FormulaR1C1 = "=1+SUMPRODUCT(--(R6C10:R33C10<RC[-4]))+SUMPRODUCT(--(R6C11:R33C11<RC[-3]),--(R6C10:R33C10=RC[-4]))"
Remove that and it should do what you want.
You will want to fully qualify your Range references that way they aren't depending on the ActiveSheet. This will provide you with consistent behavior and results.
Summary: I'm taking a row of data from one sheet and pasting it into another, however the sheet would be a daily use kind of thing where new data is just entered below old data.
Problem: On each new run, 7 is consistently added to the UsedRange.Count. For example: on one run the UsedRange.Count will be 7; the next time I run through the function the count will be 14.
What I'm Looking For: Why is this the case and is there a way to help UsedRange be more accurate
-I've included the entire Function for references' sake.
Function eftGrabber()
Dim usedRows As Integer
Dim i As Integer
ChDir "\\..."
Workbooks.Open Filename:= _
"\\...\eftGrabber.xlsm"
usedRows = Sheets("EFT").UsedRange.Count
Windows("Data").Activate
Sheets("DataSheet").Range("A11").EntireRow.Copy
Windows("eftGrabber").Activate
Sheets("EFT").Range("A" & usedRows + 1).Select
ActiveSheet.Paste
i = usedRows
Do 'THIS LOOP DELETES BLANKS AFTER POSTING NEW LINES
Range("A" & i).Select
If Range("A" & i) = "" Then
ActiveCell.EntireRow.Delete
End If
i = i - 1
Loop Until i = 1
Windows("eftGrabber").Activate
ActiveWorkbook.Save
Windows("eftGrabber").Close
End Function
Let me know if I've left out any important details. Thanks in advance!
Change: usedRows = Sheets("EFT").UsedRange.Count
To: usedRows = Sheets("EFT").Range("A" & Sheets("EFT").Rows.Count).End(xlUp).Row
Where "A" can be changed to whichever row you wish to count the total number of columns.
There is a danger in using UsedRange because it factors in such things and formatted cells with no data and other things that can give you unexpected results, like if you are expecting your data to start in Range("A1"), but it really starts in another range!
I will say, however, that If you really wish to use UsedRange, your code above is still wrong to get the rows. Use this instead UsedRange.Rows.Count or to get the last absolute cell of the UsedRange, use UsedRange.SpecialCells(xlCellTypeLastCell).Row
This two line do the magic
usedCol = ThisWorkbook.ActiveSheet.UsedRange.SpecialCells(xlCellTypeLastCell).Column
usedRow = ThisWorkbook.ActiveSheet.UsedRange.SpecialCells(xlCellTypeLastCell).Row
For more info visit Microsoft's site
http://msdn.microsoft.com/en-us/library/office/ff196157.aspx
Thanks for the discussion...
.UsedRange.Rows.Count and .UsedRange.Columns.Count work fine provided there is something in cell A1. Otherwise need to use the SpecialCells solution.
Hope this is helpful.
“UsedRange” works if you use it like this >>
x := Sheet.UsedRange.Row + Sheet.UsedRange.Rows.Count - 1;
y := Sheet.UsedRange.Column + Sheet.UsedRange.Columns.Count - 1;
Problem with SpecialCells is that you can't use it on a Protected Sheet.
Assuming you have contiguous sheet (i.e. no blank cells), and you sheet starts in A1, then I have found that
Range("A1").CurrentRegion.Rows.Count
gives the most reliable results.