Check checkbox value only once inside a nested loop - excel

I am checking the value of a checkbox on my userform inside a nested loop. I want to know if there is a way to do this before the loops because basically the code is running the same check over and over again...
what it is doing is it loops through the entire column B and combines all the rows that have the same conditions. then it puts in into an array and prints. So I need to do this checkbox check twice. Any help is appreciated!
Dim dict As Object
Dim LastRow As Long
Dim aCell As Range
Dim ArrayLen As Long
Dim LArr() As Single
Dim MPch As Boolean
MPch = UserForm1.MPCheck1.Value
Set dict = CreateObject("scripting.dictionary")
X = 0
With wks
LastRow = .Cells(.Rows.Count, "B").End(xlUp).row
ReDim LArr(LastRow)
For Each aCell In .Range("B2:B" & LastRow)
If MPch = True Then
UniqueCombo = aCell.Value & "," & aCell.Offset(0, 1) & aCell.Offset(0, 2)
Else
UniqueCombo = aCell.Value & "," & aCell.Offset(0, 1) & aCell.Offset(0, 2) & "," & aCell.Offset(0, 5)
End If
DieCoordinate = aCell.Value & "," & aCell.Offset(0, 1)
SheetName = aCell.Offset(0, 2) & "-" & aCell.Offset(0, 5)
If Not dict.exists(UniqueCombo) Then
VarLastRow = ThisWorkbook.Worksheets(SheetName).Cells(.Rows.Count, "E").End(xlUp).row + 1
ThisWorkbook.Worksheets(SheetName).Cells(VarLastRow, 5) = DieCoordinate
dict(UniqueCombo) = True 'add this value
For o = 2 To LastRow
If MPch = True Then
VariableCombo = .Cells(o, 2) & "," & .Cells(o, 3) & .Cells(o, 4)
Else
VariableCombo = .Cells(o, 2) & "," & .Cells(o, 3) & .Cells(o, 4) & "," & .Cells(o, 7)
End If
VariableCombo = .Cells(o, 2) & "," & .Cells(o, 3) & .Cells(o, 4) & "," & .Cells(o, 7)
If UniqueCombo = VariableCombo And .Cells(o, 6).Interior.ColorIndex = -4142 And _
.Cells(o, 6) <> "*" And .Cells(o, 6) <> "0" And .Cells(o, 6) <> "" Then
CDTot = CDTot + .Cells(o, 6)
LArr(X) = .Cells(o, 6)
X = X + 1
End If
Next
If X = 0 Then
ArrayLen = 0
Else
ReDim Preserve LArr(UBound(LArr) - (LastRow - X + 1))
ArrayLen = UBound(LArr) - LBound(LArr) + 1
End If
If ArrayLen < UserForm1.TextBox7 Then
ThisWorkbook.Worksheets(SheetName).Range(ThisWorkbook.Worksheets(SheetName).Cells(VarLastRow, 5), ThisWorkbook.Worksheets(SheetName).Cells(VarLastRow, 10)).Interior.ColorIndex = 53
End If
LCDUCD = 3 * Application.WorksheetFunction.StDev_P(LArr)
DieAver = Application.WorksheetFunction.Average(LArr)
ThisWorkbook.Worksheets(SheetName).Cells(VarLastRow, 7) = LCDUCD
ThisWorkbook.Worksheets(SheetName).Cells(VarLastRow, 6) = DieAver
ThisWorkbook.Worksheets(SheetName).Cells(VarLastRow, 8) = aCell.Value
ThisWorkbook.Worksheets(SheetName).Cells(VarLastRow, 9) = aCell.Offset(0, 1).Value
ThisWorkbook.Worksheets(SheetName).Cells(VarLastRow, 10) = ArrayLen
End If
ReDim LArr(LastRow)
X = 0
Next aCell
End With

Related

How to merge several cells using VBA

I have some problems with excel and VBA, in that don't know have much knowledge. I copied text from pdf and it's awful.
I have cells which contain some text.
The problem is that the text from one paragraph is broken down over several cells. At the beginning of each paragraph is a word in bold (e.g. CLR.) which describes the rest of the text. As such, it defines where each paragraph should start. How I can merge these cells into one?
I see
I want
Sub MergeText()
Dim strMerged$, r&, j&, i&
r = 1
Do While True
If Cells(r, 1).Characters(1, 1).Font.Bold Then
strMerged = "": strMerged = Cells(r, 1)
r = r + 1
While (Not Cells(r, 1).Characters(1).Font.Bold) And Len(Cells(r, 1)) > 0
strMerged = strMerged & Cells(r, 1)
r = r + 1
Wend
i = i + 1: Cells(i, 2) = strMerged
Cells(i, 2).Characters(1, InStr(1, strMerged, ".", vbTextCompare)).Font.Bold = True
Else
Exit Do
End If
Loop
End Sub
Modify (if needed) and try:
Option Explicit
Sub test()
Dim LastRow As Long, i As Long, j As Long, Count As Long
Dim str As String
With ThisWorkbook.Worksheets("Sheet1") 'Change sheet name if needed
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = LastRow To 2 Step -1
If (UCase(Left(.Range("A" & i), 1)) <> Left(.Range("A" & i), 1)) And UCase(Left(.Range("A" & i - 1), 1)) = Left(.Range("A" & i - 1), 1) Then
Count = 0
For j = 1 To Len(.Range("A" & i - 1))
If .Range("A1").Characters(j, 1).Font.FontStyle = "Bold" Then
Count = Count + 1
Else
Exit For
End If
Next j
str = .Range("A" & i - 1).Value & " " & .Range("A" & i).Value
With .Range("A" & i - 1)
.Value = str
.Font.Bold = False
With .Characters(Start:=1, Length:=Count).Font
.FontStyle = "Bold"
End With
End With
.Rows(i).EntireRow.Delete
ElseIf (UCase(Left(.Range("A" & i), 1)) <> Left(.Range("A" & i), 1)) And UCase(Left(.Range("A" & i - 1), 1)) <> Left(.Range("A" & i - 1), 1) Then
str = .Range("A" & i - 1).Value & " " & .Range("A" & i).Value
With .Range("A" & i - 1)
.Value = str
.Font.Bold = False
End With
.Rows(i).EntireRow.Delete
End If
Next i
End With
End Sub

How can I speed this vba code up which involves formatting?

I am setting up a new pricing schedule which reads selected information from a 'Register' tab, based on selected criteria, and copying this into a new tab. This data is formatted so it looks aesthetically pleasing.
I am finding formatting the code is slowing down the run speed significantly. If possible I would like to speed this up as I will be iterating this multiple times.
I hae sped the program up a reasonable amount. Initially it took 30s, whereas now it is about 10s.
I have followed information from this website as best as I can:
https://www.soa.org/News-and-Publications/Newsletters/Compact/2012/january/com-2012-iss42-roper.aspx
I feel there is still scope to improve more, though I am unsure how, and am reaching out to see if there is, or are, better ways to improve the code so it runs quicker.
Option Explicit
Sub create_pricing_schedule()
'define workbook variables
Dim Start_Time As Double, End_Time As Double
Dim file1 As Workbook
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim ws3 As Worksheet
Dim ws4 As Worksheet
Dim namedRange1 As Range
Dim namedRange2 As Range
Set file1 = ThisWorkbook
Set ws2 = file1.Worksheets("Pricing Schedule")
Set ws3 = file1.Worksheets("Control")
Set ws4 = file1.Worksheets("Register")
Set namedRange1 = file1.Names("Client_Register").RefersToRange
Set namedRange2 = file1.Names("Pricing_Range").RefersToRange
'define general variables
Dim i As Integer
Dim collect(1 To 500, 1 To 10) As Variant
Dim rw As Range
Dim selectedClient As String
Dim lastrow As Integer, lastrow2 As Integer, lastrow3 As Integer
i = 1
'time how long it takes to improve efficiency
Start_Time = Timer
'speedup so less lagg
Call speedup
'delete everything from the pricing schedule/reset
With Sheets("Pricing Schedule")
.UsedRange.ClearContents
.Cells.Interior.ColorIndex = 0
.Cells.Borders.LineStyle = xlNone
.Cells.HorizontalAlignment = xlLeft
.Cells.MergeCells = False
.Range("A:Z").WrapText = False
.Rows.RowHeight = "15"
End With
'resize the client register
lastrow = ws4.Range("A100000").End(xlUp).Row
With ActiveWorkbook.Names("Client_Register")
.RefersTo = "=Register!$A$1:$AE$" & lastrow
End With
selectedClient = ws3.Range("B3").Value
'copy from database to the pricing schedule as a non formatted list of all the info - this runs quickly, but I am open to changing it
For Each rw In Range("Client_Register").Rows
If Range("Client_Register").Cells(rw.Row, 2) = selectedClient Then
collect(i, 1) = Range("Client_Register").Range("E" & rw.Row)
collect(i, 2) = Range("Client_Register").Range("D" & rw.Row)
collect(i, 3) = Range("Client_Register").Range("F" & rw.Row)
collect(i, 4) = Range("Client_Register").Range("J" & rw.Row)
collect(i, 5) = Range("Client_Register").Range("K" & rw.Row)
collect(i, 6) = Range("Client_Register").Range("L" & rw.Row)
collect(i, 7) = Range("Client_Register").Range("M" & rw.Row)
collect(i, 8) = Range("Client_Register").Range("P" & rw.Row)
collect(i, 9) = Range("Client_Register").Range("I" & rw.Row)
collect(i, 10) = Range("Client_Register").Range("H" & rw.Row) ' used to determine if pass through fee
ws2.Range("B" & i + 6) = collect(i, 1)
ws2.Range("C" & i + 6) = collect(i, 2)
ws2.Range("D" & i + 6) = collect(i, 3)
ws2.Range("E" & i + 6) = collect(i, 4)
ws2.Range("F" & i + 6) = collect(i, 5)
ws2.Range("G" & i + 6) = collect(i, 6)
ws2.Range("H" & i + 6) = collect(i, 7)
ws2.Range("I" & i + 6) = collect(i, 8)
ws2.Range("J" & i + 6) = collect(i, 9)
ws2.Range("K" & i + 6) = collect(i, 10)
i = i + 1
End If
Next
'add in the colour and count how many rows there are
lastrow2 = ws2.Range("C5000").End(xlUp).Row
With ActiveWorkbook.Names("Pricing_Range")
.RefersTo = "='Pricing Schedule'!$A$1:$K$" & lastrow2
End With
ws2.Range("B7" & ":" & "J" & lastrow2).Interior.Color = RGB(242, 242, 242)
'==========this bit is slow, can it be quicker?==========
'add spacing, titles, and colour to sub headers
i = 7
For Each rw In Range("Pricing_Range").Rows
If Range("Pricing_Range").Cells(i, 3) <> Range("Pricing_Range").Cells(i + 1, 3) Then
Range("Pricing_Range").Rows(i + 1).Insert Shift:=xlShiftDown
Range("Pricing_Range").Rows(i + 1).Insert Shift:=xlShiftDown
Range("Pricing_Range").Rows(i + 1).Interior.ColorIndex = 0
Range("Pricing_Range").Rows(i + 2).Interior.ColorIndex = 0
Range("Pricing_Range").Range("B" & i + 2 & ":" & "J" & i + 2).Interior.Color = RGB(255, 128, 1)
Range("Pricing_Range").Range("B" & i + 2 & ":" & "J" & i + 2).Borders(xlEdgeTop).Color = RGB(0, 0, 0)
Range("Pricing_Range").Range("B" & i + 2 & ":" & "J" & i + 2).Borders(xlEdgeBottom).Color = RGB(0, 0, 0)
Range("Pricing_Range").Range("B" & i + 2).Value = Range("Pricing_Range").Range("C" & i + 3).Value
'if it is a pass through fee then add it in to the sub headers
If Range("Pricing_Range").Range("K" & i + 3).Value = "Pass-Through" Then
Range("Pricing_Range").Range("J" & i + 2).Value = "Pass-Through Fees"
Range("Pricing_Range").Range("J" & i + 2).HorizontalAlignment = xlRight
End If
i = i + 3
Else
i = i + 1
End If
Next
'==================================================
'set up the main title rows
ws2.Select
Range("Pricing_Range").Range("B2").Value = ws3.Range("B3").Value
Range("Pricing_Range").Range("B2").Font.Size = 20
Range("Pricing_Range").Range("B2").Font.Bold = True
Range("Pricing_Range").Range("B2").Font.FontStyle = "Calibri Light"
Range("Pricing_Range").Range("B2:J3").Select
With Selection
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.WrapText = False
.MergeCells = True
.Cells.Interior.Color = RGB(255, 128, 1)
.Cells.Borders(xlEdgeTop).Color = RGB(0, 0, 0)
.Cells.Borders(xlEdgeBottom).Color = RGB(0, 0, 0)
End With
'tidy up things in the sheet
With Worksheets("Pricing Schedule")
'set up the headers and first title
.Range("B6") = .Range("C7")
.Range("B5:J6").Interior.Color = RGB(255, 128, 1)
.Range("B5:J5").Borders(xlEdgeTop).Color = RGB(0, 0, 0)
.Range("B5:J5").Borders(xlEdgeBottom).Color = RGB(0, 0, 0)
.Range("B6:J6").Borders(xlEdgeTop).Color = RGB(0, 0, 0)
.Range("B6:J6").Borders(xlEdgeBottom).Color = RGB(0, 0, 0)
.Range("B5").Value = "Fee Code"
.Range("C5").Value = "Product Line"
.Range("D5").Value = "Item"
.Range("E5").Value = "Volume From"
.Range("F5").Value = "Volume To"
.Range("G5").Value = "Frequency"
.Range("H5").Value = "Location"
.Range("I5").Value = "Price"
.Range("J5").Value = "Nature of Fee"
'tidy up column widths
.Range("A5").RowHeight = 30
.Range("A1").ColumnWidth = 2
.Range("B1").ColumnWidth = 15
.Range("C1").ColumnWidth = 40
.Range("D1").ColumnWidth = 45
.Range("E1").ColumnWidth = 11
.Range("F1").ColumnWidth = 11
.Range("G1").ColumnWidth = 35
.Range("H1").ColumnWidth = 15
.Range("I1").ColumnWidth = 12
.Range("J1").ColumnWidth = 50
.Range("J:J").WrapText = True
.Range("K:K").Delete
End With
'clear the extra orange line at the end
lastrow3 = ws2.Range("B1000").End(xlUp).Row
With ws2.Rows(lastrow3 + 2)
.Cells.Interior.ColorIndex = 0
.Cells.Borders.LineStyle = xlNone
.ClearContents
End With
'add print area
With Worksheets("Pricing Schedule")
.PageSetup.Zoom = False
.PageSetup.Orientation = xlPortrait
.PageSetup.PrintArea = "$B$2:$J$" & lastrow3
.PageSetup.FitToPagesWide = 1
.PageSetup.FitToPagesTall = False
.PageSetup.PrintTitleRows = "$2:$6"
End With
'return to normal
Call slowdown
'time how long it takes to improve efficiency
End_Time = Timer
Worksheets("Control").Cells(6, 2) = End_Time - Start_Time
End Sub
Sub speedup()
Application.Calculation = xlManual
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.DisplayStatusBar = False
End Sub
Sub slowdown()
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True
Application.DisplayStatusBar = True
End Sub
I found a few lines that could save you some execution time.
'****EDIT****Changed this to direct range reference rather than go through the Names collection.
'Set namedRange1 = file1.Names("Client_Register").RefersToRange
'Set namedRange2 = file1.Names("Pricing_Range").RefersToRange
Set namedRange1 = file1.Range("Client_Register")
Set namedRange2 = file1.Range("Pricing_Range")
Used range takes more time rather use .cells directly
'delete everything from the pricing schedule/reset
'****EDIT***
With ws2 'Sheets("Pricing Schedule")
'used range takes more time rather use .cells directly
.Cells.ClearContents
Rather than use arrays you can directly update values as shown below
'I am using i for the row count
ws2.Range("B" & i + 6).Value = namedRange1.Cells(i, 5).Value
ws2.Range("C" & i + 6).Value = namedRange1.Cells(i, 4).Value
ws2.Range("D" & i + 6).Value = namedRange1.Cells(i, 6).Value
ws2.Range("E" & i + 6).Value = namedRange1.Cells(i, 10).Value
ws2.Range("F" & i + 6).Value = namedRange1.Cells(i, 11).Value
ws2.Range("G" & i + 6).Value = namedRange1.Cells(i, 12).Value
ws2.Range("H" & i + 6).Value = namedRange1.Cells(i, 12).Value
ws2.Range("I" & i + 6).Value = namedRange1.Cells(i, 16).Value
ws2.Range("J" & i + 6).Value = namedRange1.Cells(i, 9).Value
ws2.Range("K" & i + 6).Value = namedRange1.Cells(i, 8).Value
i = i + 1
The main culprit for your slower performance is the insert operation. try to work the logic to not having insert. If not possible, try to insert rows outside the loop in a single operation rather than in the loop
Range("Pricing_Range").Rows(i + 1).Insert Shift:=xlShiftDown
Range("Pricing_Range").Rows(i + 1).Insert Shift:=xlShiftDown
Your handling of the collect array is inefficient. Consider reading the entire Client Register into an array with MyArray = Range.Value. Then prepare the output array in memory and write it to the worksheet after all looping is done, in one go, with TargetRange.Value = collect.
Avoid inserting rows. What's wrong with the existing? If you are preparing all data in an array to be pasted to the worksheet, empty array elements will produce empty worksheet cells. In this way all inserting can be avoided and all you need to do is to format.
There is time cost for every access to the worksheet, whether to read or write. Even for formatting, try to create ranges that are treated in the same manner. Avoid accessing the worksheet in loops.
Example of With and block assignment from an array:
'copy from database to the pricing schedule as a
' non formatted list of all the info - this runs quickly,
' but I am open to changing it
With Range("Client_Register")
For Each rw In .Rows
If .Cells(rw.Row, 2) = selectedClient Then
collect(i, 1) = .Range("E" & rw.Row)
collect(i, 2) = .Range("D" & rw.Row)
collect(i, 3) = .Range("F" & rw.Row)
collect(i, 4) = .Range("J" & rw.Row)
collect(i, 5) = .Range("K" & rw.Row)
collect(i, 6) = .Range("L" & rw.Row)
collect(i, 7) = .Range("M" & rw.Row)
collect(i, 8) = .Range("P" & rw.Row)
collect(i, 9) = .Range("I" & rw.Row)
collect(i, 10) = .Range("H" & rw.Row)
'you could even skip the row-by-row population of values
' and assign as a block after exiting the loop
ws2.Range("B" & i + 6).Resize(1, 10).Value = _
Array(collect(i, 1), collect(i, 2), collect(i, 3), _
collect(i, 4), collect(i, 5), collect(i, 6), _
collect(i, 7), collect(i, 8), collect(i, 9), _
collect(i, 10))
i = i + 1
End If
Next
End With
Note this will break if your Client_Register refers to a range which doesn't start on Row1, because of the relative range references.
Eg:
Range("A1:A10").Range("A1") 'refers to A1
Range("A2:A10").Range("A1") 'refers to A2

Do While Loop for SKU numbers

I am trying to automate my SKU numbers. I have 3 columns. The first column has 28, the second has 6 and finally the third has 58.
I want the SKU to have a Trend like so 0{(###)col1}{(##)col2}{(##)col3}0
My Code looks like this
Sub SKU()
Dim x As Long
x = 1
i = 1
j = 1
k = 1
Do While Cells(i, 1) <> ""
Do While Cells(j, 2) <> ""
Do While Cells(k, 3) <> ""
Cells(x, 4).Value = Format(0, "0") & Format(i, "000") & _
Format(j, "00") & Format(k, "00") & Format(0, "0")
k = k + 1
x = x + 1
Loop
j = j + 1
Loop
i = i + 1
Loop
End Sub
No need to use the Do Loop. Find the last row and then use a For loop.
Is this what you are trying?
Sub Sample()
Dim ws As Worksheet
Dim lRow As Long, i As Long
'~~> Change this to the relevant sheet
Set ws = ThisWorkbook.Sheets("Sheet2")
With ws
'~~> Find last row
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
For i = 1 To lRow
If .Cells(i, 1) <> "" And .Cells(i, 2) <> "" And .Cells(i, 3) <> "" Then
'0{(###)col1}{(##)col2}{(##)col3}0
.Cells(i, 4).Value = "'0" & _
Format(.Cells(i, 1), "000") & _
Format(.Cells(i, 2), "00") & _
Format(.Cells(i, 3), "00") & _
"0"
End If
Next i
End With
End Sub
Output for 28,6,58 is 002806580
As i mentioned in the comment to the question, remove first and second do-while loop then replace:
Cells(x, 4).Value = Format(0, "0") & Format(i, "000") & _
Format(j, "00") & Format(k, "00") & Format(0, "0")
with:
Cells(k, 4) = "'" & Format(Cells(k, 1), "000") & _
Format(Cells(k, 2), "00") & Format(Cells(k, 3), "00")
Result: 0280658
In case you want to add leading and ending zeros:
Cells(k, 4) = "'0" & Format(Cells(k, 1), "000") & _
Format(Cells(k, 2), "00") & Format(Cells(k, 3), "00") & "0"
Result: 002806580

A better way to union two excel tables

I have two tables
A B C
name surname address
and
A B C D
id address name surname
I need to union the tables and matching the cols, so
table1, colA = table2, colC
table1, colC = table2, colB
etc
I use this code, which works fine, but for big data is slow
Sub unionrep()
Dim lastRow As Long
Sheets("decl").Select
With ActiveSheet
lastRow = .Cells(.Rows.Count, "b").End(xlUp).Row
End With
With Sheets("onl")
tlastRow = .Cells(.Rows.Count, "b").End(xlUp).Row
End With
For i = 1 To lastRow
Sheets("onl").Range("a" & tlastRow + i + 1).Value = Range("a" & i).Value
Sheets("onl").Range("b" & tlastRow + i + 1).Value = Trim(Range("b" & i).Value)
Sheets("onl").Range("c" & tlastRow + i + 1).Value = "*" & Range("c" & i).Value
Sheets("onl").Range("d" & tlastRow + i + 1).Value = Range("g" & i).Value
Sheets("onl").Range("e" & tlastRow + i + 1).Value = Range("d" & i).Value
Sheets("onl").Range("f" & tlastRow + i + 1).Value = ""
Sheets("onl").Range("g" & tlastRow + i + 1).Value = ""
Sheets("onl").Range("h" & tlastRow + i + 1).Value = ""
Sheets("onl").Range("i" & tlastRow + i + 1).Value = Range("e" & i).Value
Sheets("onl").Range("j" & tlastRow + i + 1).Value = Range("i" & i).Value
Sheets("onl").Range("k" & tlastRow + i + 1).Value = Range("f" & i).Value
Next
Sheets("onl").Select
End Sub
You could copy and paste the entire ranges instead of looping through the rows. For example, to copy from column A in the "decl" sheet to column C in the "onl" sheet, something like:
Sheets("decl").Range(Cells(1, 1), Cells(lastRow, 1)).Copy
Sheets("onl").Range("C" & tlastRow + 1).PasteSpecial
Try using arrays:
Sub unionrep()
Dim lastRow As Long
Dim vDataIn, vDataOut
With Sheets("decl")
lastRow = .Cells(.Rows.Count, "b").End(xlUp).Row
vDataIn = .Range("A1:I" & lastRow).Value
End With
ReDim vDataOut(1 To lastRow, 1 To 11)
With Sheets("onl")
tlastRow = .Cells(.Rows.Count, "b").End(xlUp).Row + 1
End With
For i = 1 To lastRow
vDataOut(i, 1) = vDataIn(i, 1)
vDataOut(i, 2) = Trim(vDataIn(i, 2))
vDataOut(i, 3) = "*" & vDataIn(i, 3)
vDataOut(i, 4) = vDataIn(i, 7)
vDataOut(i, 5) = vDataIn(i, 4)
vDataOut(i, 9) = vDataIn(i, 5)
vDataOut(i, 10) = vDataIn(i, 9)
vDataOut(i, 11) = vDataIn(i, 6)
Next
Sheets("onl").Range("a" & tlastRow).Resize(UBound(vDataOut, 1), UBound(vDataOut, 2)).Value = vDataOut
Sheets("onl").Select
End Sub

Using a string to represent the criteria for an if function in VBA

I was hoping someone will have an answer to this. I don't think it is possible but what I am trying to do is set up an if function using a string as the criteria. For example:
With ThisWorkbook.Worksheets("Sheet1")
stNumerator = .Cells(6, 3).Value
stDenominator = .Cells(6, 4).Value
If .Cells(7, 3) = "x" Then
stCriteria = stNumerator & " >0"
End If
If .Cells(8, 4) = "x" Then
stCriteria = stCriteria & " and " & stDenominator & " <>0"
End If
If stCriteria Then
.Cells(1, 1) = stNumerator / stDenominator
End If
So stCriteria should equal stNumerator > 0 and stDenominator <>0
What you want can be achieved using Application.Evaluate
Here is an example
Sub Sample()
Dim stCriteria1 As String, stCriteria2 As String
With ThisWorkbook.Worksheets("Sheet1")
stNumerator = .Cells(6, 3).Value
stDenominator = .Cells(6, 4).Value
If .Cells(7, 3) = "x" Then stCriteria1 = stNumerator & " >0"
If .Cells(8, 4) = "x" Then stCriteria2 = stDenominator & " <>0"
If stCriteria1 <> "" And stCriteria2 <> "" Then
If Application.Evaluate(stCriteria1) And _
Application.Evaluate(stCriteria2) Then
.Cells(1, 1) = stNumerator / stDenominator
End If
ElseIf stCriteria1 <> "" Then
If Application.Evaluate(stCriteria1) Then
.Cells(1, 1) = stNumerator / stDenominator
End If
ElseIf stCriteria2 <> "" Then
If Application.Evaluate(stCriteria2) Then
.Cells(1, 1) = stNumerator / stDenominator
End If
End If
End With
End Sub

Resources