help with conveting excel formula to vba??

cbrf23

Board Regular
Joined
Jun 20, 2011
Messages
241
Hello,

I'm new to VBA and writing macros, but now that I've discovered it, I really want to use it for a current project because I know that it will make things a LOT easier and a LOT less complicated if I could do what I'm currently by using a macro in VBA.

I would really appreciate some help with this!

Lets say I'm using the following formula, which I have pasted all down column D. Based on whatever row we've pasted this into, were going to see whats in column B, then check whats in column C, then check to see if I2 contains anything (this is a box I use to switch between metric and standard), and based on all this criteria, we output something like:
whateverswritteninB3 (0.000)
Code:
=B3&IF(ISBLANK($C3),"",IF(ISBLANK$I$2)," ("&TEXT($C3,"0.000")&")"," ("TEXT(($C3/25.4),"0.0000")&")"))

I'd really like to do this in VBA.
I dont know the proper syntax, but in my head I'm thinking
Code:
dim InDes as ??, InVal as ??
InDes = target.offset(0,-2) 'this cell could contain text or a formula...in I want to display whatever the cell is actually showing. 
InVal = if target.offset(0,-1) = "" then InVal = "" 
else
if cell I2 is empty, then InVal = value.target.offset(0,-1)
else
if cell I2 is not empty, then InVal = value.target.offset(0,-1)/25.4
 
If (Not Intersect(Target, Range("D:D")) Is Nothing) Then
            If (Not IsEmpty(Target)) Then
                    'help with syntax here
                    if InVal = "" then
                    target = InDes
                    else
                    target = essentially the equivalent of:
                    InDes&" ("&InVal&")"
 
Ok, I'm 99% done with this project, and I have one small problem.

I wrote some more code so that if I delete an entry (an entry being a whole row) off my input page, it will remove the corresponding entry off my output page. It almost works as I expected....the issue is that the item number (column A on both input and output) instead of being cleared, becomes a zero.

I'm pretty stumped on this one... I even turned off application events thinking maybe that was causing it, but still the same.
Code:
Else '//if target is empty
intInRow = Target.Row '//row number of starting cell
Set rngInRow = Range("A" & intInRow).Rows("1:1").EntireRow
Set rngInCell = Range("I" & rngInRow.Row)
If funRowEmpty(Target) = False Then
    Application.ScreenUpdating = True
    Exit Sub
    Else
    If funRowEmpty(Target) = True Then
    Application.EnableEvents = False
    'rngInRow.ClearContents
    intOutRow = intInRow + 5
    Set rngOutRow = Range("A" & intOutRow).Rows("1:1").EntireRow.ClearContents
    Application.EnableEvents = True
    End If

and function to figure out if row is empty :
Code:
Public Function funRowEmpty(rngCell As Range) As Boolean
Dim rngValues As Range
Dim rngFormulas As Range
Dim rngRange As Range
 
Set rngRange = Range("A:G")
 
On Error Resume Next
Set rngValues = Intersect(rngCell.EntireRow.SpecialCells(xlConstants), rngRange)
Set rngFormulas = Intersect(rngCell.EntireRow.SpecialCells(xlFormulas), rngRange)
On Error GoTo 0
 
If rngValues Is Nothing And rngFormulas Is Nothing Then
    funRowEmpty = True
Else
    funRowEmpty = False
End If
End Function
 
Upvote 0

Excel Facts

Select a hidden cell
Somehide hide payroll data in column G? Press F5. Type G1. Enter. Look in formula bar while you arrow down through G.
I don't see anything in this code that would result in a zero being in Column A of either sheet. It hard to tell without seeing all the code what might be the cause of the problem.

When you are having problems with the code and you can't find where the problem is by examining the code you can use the debugging tools. There are articles and videos on the subject that can explain the process better than I can. Try
• Chip Pearson's site Debugging VBA
• YouTube - Watches and More Debugging Strategies
• YouTube - Stepping and Breakpoints
• Or just google VBA Debugging

Though, my goto debugging approach is to place a break point (F9) on a line right before I suspect I may have made a mistake, run the code, it will stop at the break point, and then I step through the code using F8. Checking the output and variable values as I go.
 
Upvote 0
Thanks Ralajer,

I will do some more debugging tomorrow when I get back to the office.

I was a little stumped as well...not sure why its doing that. I'll have to see if I can pinpoint when that output is being generated.

I've been using the same technique, breakpoint then step through with f8. ;)
 
Upvote 0
Fixed it.

First I changed
Code:
    Set rngOutRow = Range("A" & intOutRow).Rows("1:1").EntireRow.ClearContents
    Application.EnableEvents = True
    End If
to
Code:
    Set rngOutRow = Range("A" & intOutRow).Rows("1:1").EntireRow
    rngOutRow.ClearContents
    Application.EnableEvents = True
    End If

then that didnt help.

so I ended up delcaring the item number as string instead of double and fixed everything.

I dont understand though, why that should matter. I mean the part of the code I'm working with is dealing with a constant that is already in the cell. Shouldn't .ClearContents be the same as hitting the delete key?
 
Last edited:
Upvote 0
As far as I know the ClearContents method should act the same way as pressing the delete key. I not sure why changing the type from double to string made a difference. I would have to see all the code to say for sure it wasn't a VBA issue.

This isn't related to the problem just a note on a easier way to define a whole row. The below two lines do the same thing.
Code:
Set rngOutRow = Range("A" & intOutRow).Rows("1:1").EntireRow
Set rngOutRow = Rows(intOutRow)
 
Upvote 0
Nice tip! I like trying to make my code as clean and easy to read/understand as possible, so thats handy.

I appreciate all the help. Believe it or not, I'm learning a TON through this process and through your help, so thanks again for everything!

I dont know why, but when I was debugging, I found that clearcontents wasnt clearing the whole row.

No errors were present, and I'm convinced it was executing (plus I couldn't undo(using ctrl-z) the action afterwards) but it wouldnt delete the last entry. I have no idea why...it doesn't make much sense to me, but then again this is all pretty new to me.

I changed the code so it just runs through the output process again whenever I delete an entry, so it then outputs as empty. To me this doesn't seem like it would be the most efficient way, but it works well, and since its only dealing with one row at a time I dont think it will be an issue. Plus if I do it this way, the undo function still works.

I can post the code up tomorrow when I'm at work if you'd like to take a look. Maybe you'll see something that I'm not seeing. Also, there are probably other things in there I could do easier or more efficiently as well that you might see ;)

Tomorrow I want to add something that will recalculate a section if I change more than one row at a time....like if I select a range involving multiple rows and hit delete or something like that. I think I know how I'm going to approach that, so I'll try to get that done tomorrow before posting.
 
Last edited:
Upvote 0
So everything is working great now :)

I did find two things I have questions about though.

One, is that I cant use undo after running the unitChange section of code. I'm thinking this might have to do with using .ClearContents, but I'm not positive.
--If this is the case, is there an equivalent way to do the same thing as .ClearContents, that would allow the undo function to work afterwards?


The other, is that if I delete a row (right-click delete row) in the middle of my input data, on the output page, I end up with a duplicate line.
--Is there a way to identify when a row has been deleted? That way I could I could add a boolean value for a row delete (blnRowDel) and use it like I do "blnUnit" to goto and run my reEvaluate section of code (in the Worksheet_Change Sub):
Code:
if [row delete event just happened] then
blnRowDel = true 
GoTo reEvaluate
End If
 
'//and code for if blnRowDel = true GoTo worksheetExitHandler
Here is the code if you want to take a look...

Code:
Sub Worksheet_Change(ByVal Target As Range)
'/////////////////////////
'//str for string
'//rng for range
'//lng for long
'//int for integer
'//sgl for single
'//dbl for double
'//bln for boolean
'//byt for byte
'/////////////////////////
Dim strInBk         As String '//name of input workbook
Dim strOutBk        As String '//name of output workbook
Dim strInSht        As String '//name of input sheet
Dim strOutSht       As String '//name of output sheet
Dim intInRowTarget  As Integer '//intInRow target
Dim rngInCellTarget As Range '//rngInCell target
Dim blnReVal        As Boolean '//re-evaluation in progress true/false
Dim blnUnit         As Boolean '//re-evaluation due to unit change true/false
Dim intActiveSel    As Integer '//rows in active selection range
'/////////////////////////
'//Set Variables:
blnReVal = False
blnUnit = False
strInBk = "Book3.xls"
strOutBk = "Book3.xls"
strInSht = "INPUT"
strOutSht = "TEST"
intActiveSel = Selection.Rows.Count
'////****On Error****////
On Error GoTo worksheetErrHandler
'/////////////////////////
If Target.Address = "$H$2" Then
blnUnit = True
GoTo unitChange
ElseIf intActiveSel > 1 Then
GoTo reEvaluate
ElseIf Target.Column <= Columns("I").Column And Target.Row > 2 Then
intInRowTarget = funInRowTarget(Target)
Set rngInCellTarget = funInCellTarget(Target)
blnReVal = False
GoTo inputChange
End If
'/////////////////////////
'////***inputChange***////
inputChange:
'/////////////////////////
Dim rngInCell       As Range '//starting cell on input sheet
Dim rngInRow        As Range '//starting row on input sheet
Dim intInRow        As Integer '//row number of the active cell on input sheet
Dim rngOutRow       As Range '//starting row on output sheet
Dim intOutRow       As Integer '//row number of the active cell on output sheet
Dim rngOutCell      As Range '//starting cell on output sheet
Dim dblInItem       As Double '//item number from input sheet
Dim dblOutItem      As Double '//item number to output sheet
Dim strOutItem      As String '//item number to output sheet in string format
Dim strOutDesc      As String '//description from function to output sheet
Dim strInMethod     As String '//data from method field on input sheet
Dim strOutMethod    As String '//data to method field on output sheet
Dim strInZone       As String '//data from zone field on input sheet
Dim strOutZone      As String '//data to method field on output sheet
'/////////////////////////
Application.ScreenUpdating = False
'//Set Working Row:
intInRow = intInRowTarget
Set rngInCell = rngInCellTarget
Set rngInRow = Rows(intInRow)
Set rngInCell = Range("I" & rngInRow.Row)
'//Get Input Variables:
dblInItem = rngInCell.Offset(0, -8).Value
strInMethod = rngInCell.Offset(0, -3).Value
strInZone = rngInCell.Offset(0, -2).Value
'//Set Output Variables:
dblOutItem = dblInItem
strOutItem = dblOutItem
If strOutItem = 0 Then strOutItem = ""
strOutDesc = funDescription(intInRow, rngInCell)
strOutMethod = strInMethod
strOutZone = strInZone
'//Set Output Range:
intOutRow = intInRow + 5
Set rngOutRow = Rows(intOutRow)
'//Output Data to Output Sheet:
Sheets(strOutSht).Range("A" & rngOutRow.Row).Value = strOutItem
Sheets(strOutSht).Range("B" & rngOutRow.Row).Value = strOutDesc
Sheets(strOutSht).Range("C" & rngOutRow.Row).Value = strOutMethod
Sheets(strOutSht).Range("D" & rngOutRow.Row).Value = strOutZone
'/////////////////////////
'//Exit:
If blnReVal = False Then
GoTo worksheetExitHandler
Else
GoTo contReval
End If
'/////////////////////////
'////***unitChange***////
unitChange:
'/////////////////////////
Dim intReply        As Integer
Dim blnChoice       As Boolean
'/////////////////////////
If Target.Value = "" Then blnChoice = False Else blnChoice = True
'/////////////////////////
    If blnChoice = False Then
    intReply = MsgBox(prompt:="STANDARD units have been selected." & Chr(13) & "Would you like your project, " & strInBk & ", to reflect this change?", _
        Buttons:=vbYesNoCancel, Title:="PROJECT UNITS CHANGE")
    '/////////////////////////
    Else
    intReply = MsgBox(prompt:="METRIC units have been selected." & Chr(13) & "Would you like your project, " & strInBk & ", to reflect this change?", _
        Buttons:=vbYesNoCancel, Title:="PROJECT UNITS CHANGE")
    '/////////////////////////
    End If
'/////////////////////////
    If intReply = vbYes Then
    GoTo reEvaluate
    '/////////////////////////
    ElseIf intReply = vbNo Then
    Sheets(strInSht).Select
    Sheets(strInSht).Range("H2").Select
    GoTo worksheetExitHandler
    '/////////////////////////
    Else
    Sheets(strInSht).Select
    Sheets(strInSht).Range("H2").Select
    GoTo worksheetExitHandler
    '/////////////////////////
    End If
'/////////////////////////
'////***reEvaluate***////
reEvaluate:
'/////////////////////////
Application.EnableEvents = True
'/////////////////////////
Dim rngInTarget     As Range '//target range of input sheet
Dim rngOutTarget    As Range '//target range of output sheet
Dim strInRange      As String '//usable range of input sheet
Dim strOutRange     As String '//usable range of output sheet
Dim rngInRange      As Range '//usable range of input sheet
Dim rngOutRange     As Range '//usable range of output sheet
Dim rngInLine       As Range '//working line on input sheet
Dim rngOutLine      As Range '//working line on output sheet
Dim intInLine       As Integer '//number of working line on input sheet
Dim intInLast       As Integer '//last line of rngInRange
'/////////////////////////
Application.ScreenUpdating = False
'/////////////////////////
'//Set Variables:
blnReVal = True
Set rngInRange = Workbooks(strInBk).Sheets(strInSht).Range("A3:AA65536")
Set rngOutRange = Workbooks(strOutBk).Sheets(strOutSht).Range("A8:AA65536")
'/////////////////////////
'//Clear Output Sheet of Current Data:
Workbooks(strOutBk).Sheets(strOutSht).Select
If blnUnit = True Then
Set rngOutTarget = Intersect(funTrueUsedRange, rngOutRange)
    If (Not rngOutTarget Is Nothing) Then
    rngOutTarget.Select
    rngOutTarget.ClearContents
    End If
End If
'/////////////////////////
'//Set Range to Evaluate on Input Sheet:
Workbooks(strInBk).Sheets(strInSht).Select
If blnUnit = True Then
    Set rngInTarget = Intersect(funTrueUsedRange, rngInRange)
    Else
    Set rngInTarget = Selection
    End If
rngInTarget.Select
'//Find Last Row:
intInLast = rngInTarget.Rows.Count
'/////////////////////////
'//For Each Line:
For Each rngInLine In rngInTarget
intInLine = intInLine + 1
intInRowTarget = funInRowTarget(ActiveCell)
Set rngInCellTarget = funInCellTarget(ActiveCell)
    If intInLine > intInLast Then
        If blnUnit = True Then MsgBox ("Unit conversion complete")
    GoTo worksheetExitHandler
    End If
GoTo inputChange
'////***contReval***////
contReval:
ActiveCell.Offset(1, 0).Select
Next rngInLine
'/////////////////////////
'//Select H2 and Exit:
If blnUnit = True Then
    Sheets(strInSht).Select
    Sheets(strInSht).Range("H2").Select
    End If
GoTo worksheetExitHandler
'/////////////////////////
'////***ErrHandler***////
worksheetErrHandler:
Dim rngFieldName        As Range
Dim strFieldName        As String
Set rngFieldName = Intersect(Target.Columns.EntireColumn, Range("A1").Rows.EntireRow)
strFieldName = rngFieldName.Value
If Err.Number = 13 Then
    MsgBox "Incorrect data format for field:  ''" & strFieldName & "''", Title:="DATA FORMAT ERROR"
    ElseIf Err.Number = 1004 Then
        GoTo worksheetExitHandler
    Else
        MsgBox "An error occurred" & Chr(13) & "Error Number:" & Chr(13) & Err.Number, Title:="ERROR: " & Err.Number
    End If
GoTo worksheetExitHandler
'/////////////////////////
'////***ExitHandler***////
worksheetExitHandler:
Application.ScreenUpdating = True
Application.EnableEvents = True
Exit Sub
'/////////////////////////
'////***End Sub****////
End Sub
 
Upvote 0
I am not sure which actions would result in the undo stack from not being cleared. There are several method for working around the undo issue I've never implemented one myself but there was a post regarding this recently with board user VoG suggested this link http://www.j-walk.com/ss/excel/tips/tip23.htm

I am not sure if the action that prompted the change event can be directly determined. There is a way to handle it indirectly which consists of looking at something on the sheet that would have changed if the a row was deleted. For this I'd use the last row number of the data in column A. The number of the last row prior to the change is stored either in module level variable or in a cell. Then when a change event occurs it can be checked against the current last row if it's less than the previous then I it can be assumed that a row has been deleted. Here is a solution using a module level variable.
Code:
'// Variable must be defined outside a sub to give it persistence
'//  between calls of the sub. This variable will be persistent for as long
'//  as the workbook stays open (or until VBA hit a snag)
Dim PreviousLastRow As Long

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim CurrentLastRow As Long
    Dim blnRowDel  as Boolean
    Application.EnableEvents = False
    '// Last row in Column A that contains data
    CurrentLastRow = Cells(Rows.Count, 1).End(xlUp).Row
    
    '// If the change results in the current last row from being less
    '//  than the previous last row was most likely deleted.
    blnRowDel = CurrentLastRow < PreviousLastRow
    
    '// Set Previous last row to current last row
    PreviousLastRow = CurrentLastRow
    
    If blnRowDel = True Then GoTo reEvaluate
    '... CODE continues

End Sub
This doesn't work if the first change event on the sheet after opening the workbook is deleting a row. Because the variable PreviousLastRow has to be initialized and currently it is only initialized on change events. If that is a concern you can store the PreviousLastRow in a cell rather than a variable or initialize it when the workbook opens.
 
Upvote 0
Trying to change my metric qualifier to option buttons...
I need to get the on change event for the button to set a boolean variable true, and then run through the worksheet on change event sub... is this possible? Heres what I have, but it says label not defined
Code:
Private Sub OptionButton1_Change()
Dim blnUnitChange       As Boolean
blnUnitChange = True
GoTo Worksheet_Change
End Sub
Sub Worksheet_Change(ByVal Target As Range)
'//my onchange code
 
Upvote 0

Forum statistics

Threads
1,224,598
Messages
6,179,822
Members
452,946
Latest member
JoseDavid

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top