VBA and Excel optimization of processing time, dealing with several rows - excel

Hello StackOverflowers,
I need som help here.
I have been working on a VBA code but it is taking around 20 to 30 mins to process the data and I need some advise to reduce the amount the processing time.
I have 3 sheets in the document.
1- Sheet 1 is called "ExtractData".
That sheet contains 3 columns:
Column A: contains "Environment: PROD, Pre-Prod & UAT", responsible fetching the data based on the environment stated in the dropdown list.
That column contains also a possibility to parse the html text contained in some cells
Column B: Contain list of Product Code
Column C: contains name of fields / attribute for which we need the data for.
Also, we have a button in that sheet that should run the code to fetch the data and display them in sheet called "Source Data"
2- Sheet 2: Called "DataReview", containing extracted data, then I copy data content from cell A2:MJ500 and paste it in sheet 3 (Source Data) that contains some predefined headers.
So I paste data from A4
3- Sheet 3 called: "Source Data"
That sheet will display all data fetched based on the stated attribute
CASE 1: What I am supposed to do, is to filter the data based on some variable and transpose them in a separate sheet:
Exemple 1: May via a VBA buttong, I select specific attribute, like filter based on "Product Family", when you click run, it will copy the data,
then transpose them in a specific way in a separate sheet named after the Product family name
BUT, I tried, different ways and I am not getting what I wanted.
Below find the code I am using, please go through it and help me make it better.
Function Get_File(Enviromment As String, Pos_row As Integer, Data_date As String) As String
Dim objRequest As Object
Dim blnAsync As Boolean
Dim strResponse As String
Dim Token As String
Dim Url As String
Dim No_product_string As String
Token = "xxxxxxxx"
Url = CreateURL(Enviromment, Pos_row, Data_date)
Set objRequest = CreateObject("MSXML2.XMLHTTP")
blnAsync = True
With objRequest
.Open "GET", Url, blnAsync
.SetRequestHeader "Content-Type", "application/json"
.SetRequestHeader "x-auth-token", "xxxxxxxx"
.Send
'spin wheels whilst waiting for response
While objRequest.ReadyState <> 4
DoEvents
Wend
strResponse = .ResponseText
End With
Debug.Print strResponse
Get_File = strResponse
End Function
Function CreateURL(Enviroment As String, Pos_row As Integer, Data_date As String)
Dim product_code As String
If (StrComp(Enviroment, "UAT", vbTextCompare) = 0) Then
CreateURL = "https://TEST1-uat.Nothing.net:8096/api/products/hierarchies"
ElseIf (StrComp(Enviroment, "PPROD", vbTextCompare) = 0) Then
CreateURL = "https://TEST1-pprod.nothing.net:8096/api/products/hierarchies"
ElseIf (StrComp(Enviroment, "PROD", vbTextCompare) = 0) Then
CreateURL = "https://TEST1.nothing.net:8096/api/products/hierarchies"
Else
CreateURL = "https://TEST1.nothing.net:8096/api/products/hierarchies"
End If
If Pos_row <> -1 Then
product_code = ThisWorkbook.Sheets("DataReview").Cells(Pos_row, 1)
CreateURL = CreateURL & "?query=%7B%22productCode%22%3A%22" & product_code & "%22%7D"
End If
If Not (Trim(Data_date & "") = "") Then
CreateURL = Left(CreateURL, Len(CreateURL) - 3) & "%2C%22date%22%3A%22" & Data_date & "%22%7D"
End If
End Function
Function Get_value(Json_file As String, Field_name As String, Initial_value As String, Current_amount_values As Integer) As String
Dim tempString As String
Dim Value As String
Dim Field_name_temp As String
Field_name_temp = "my_" & Field_name 'Ensure that field name is not subset of other field name
Value = Initial_value
Pos_field = InStr(Json_file, Field_name_temp & """:")
tempString = Mid(Json_file, Pos_field + Len(Field_name_temp) + 4)
'MsgBox (Mid(tempString, 1, 75))
If Not StrComp(Left(tempString, 1), "}") Then
Value = Value & "," & ""
Else
Value = Value & "$" & Replace(Split(tempString, "]")(0), """", "")
End If
If Not InStr(tempString, Field_name_temp & """:") = 0 Then
Value = Get_value(tempString, Field_name, Value, Current_amount_values + 1)
End If
Get_value = Value
End Function
Sub Set_value(Value As String, Pos_col As Integer, Pos_row As Integer, Pos_row_max As Integer)
Dim i As Integer
Dim HTML As String
HTML = ThisWorkbook.Sheets("ExtractData").Range("A8")
If HTML = "Yes" Or HTML = "" Then
Value = ParseHTML(Value)
End If
If Value <> "" Then
If UBound(Split(Value, "$")) = 0 Then
ThisWorkbook.Sheets("DataReview").Cells(Pos_row, Pos_col).Value = Value
Else
If Pos_row < Pos_row_max And ThisWorkbook.Sheets("DataReview").Cells(Pos_row + 1, 1) <> "" Then
ThisWorkbook.Sheets("DataReview").Cells(Pos_row, Pos_col).Value = Split(Value, "$")(0)
For i = 1 To UBound(Split(Value, "$"))
ThisWorkbook.Sheets("DataReview").Cells(Pos_row, Pos_col).Offset(1).EntireRow.Insert
ThisWorkbook.Sheets("DataReview").Cells(Pos_row + 1, Pos_col).Value = Split(Value, "$")(i)
Next i
End If
ThisWorkbook.Sheets("DataReview").Cells(Pos_row, Pos_col).Value = Split(Value, "$")(0)
For i = 1 To UBound(Split(Value, "$"))
ThisWorkbook.Sheets("DataReview").Cells(Pos_row + i, Pos_col).Value = Split(Value, "$")(i)
Next i
End If
End If
End Sub
Public Function ParseHTML(ByVal Value As String) As String
Dim htmlContent As New HTMLDocument
htmlContent.body.innerHTML = Value
ParseHTML = htmlContent.body.innerText
End Function
Sub Main_script()
Dim Pos_col As Integer, Pos_row As Integer, Json_file As String, Field_name As String
Dim Value As String
Dim i As Integer
Dim tempValue As String
Dim Pos_row_max As Integer
Dim Enviromment As String
Dim Data_date As String
Pos_col = 2
Pos_row = 2
Call Prepare_sheet
Data_date = Format(ThisWorkbook.Sheets("ExtractData").Range("A5"), "YYYY-MM-DD")
Enviromment = ThisWorkbook.Sheets("ExtractData").Range("A2")
Do While Not IsEmpty(ThisWorkbook.Sheets("DataReview").Cells(Pos_row, 1).Value)
Json_file = Get_File(Enviromment, Pos_row, Data_date)
Do While Not IsEmpty(ThisWorkbook.Sheets("DataReview").Cells(1, Pos_col).Value)
Field_name = ThisWorkbook.Sheets("DataReview").Cells(1, Pos_col).Value
Value = Mid(Get_value(Json_file, Field_name, "", 0), 2) 'Mid() is used to remove "," from the front of values
Pos_row_max = Application.Max(Pos_row_max, Pos_row + UBound(Split(Value, "$")))
Call Set_value(Value, Pos_col, Pos_row, Pos_row_max)
Pos_col = Pos_col + 1
Loop
Pos_col = 2
Pos_row = Pos_row_max + 1
Loop
ThisWorkbook.Sheets("DataReview").Activate
'Columns.AutoFit
'Rows.AutoFit
Cells.Select
Selection.ColumnWidth = 32
Selection.RowHeight = 15
ThisWorkbook.Sheets("DataReview").Range("A2:HM10000").Select
Selection.Copy
Sheets("Source Data").Select
Sheets("Source Data").Range("A4:HM14000").Select
ActiveSheet.Paste
ThisWorkbook.Sheets("Source Data").Activate
End Sub
Sub Prepare_sheet()
Dim i As Integer
Dim j As Integer
i = 2
j = 2
ThisWorkbook.Sheets("DataReview").Range("A1:HH10000").ClearContents
Do While ThisWorkbook.Sheets("ExtractData").Cells(i, 2).Value <> ""
ThisWorkbook.Sheets("DataReview").Cells(i, 1).Value = ThisWorkbook.Sheets("ExtractData").Cells(i, 2).Value
i = i + 1
Loop
Do While ThisWorkbook.Sheets("ExtractData").Cells(j, 3).Value <> ""
ThisWorkbook.Sheets("DataReview").Cells(1, j).Value = ThisWorkbook.Sheets("ExtractData").Cells(j, 3).Value
j = j + 1
Loop
ThisWorkbook.Sheets("DataReview").Cells(1, 1).Value = "Product_code"
End Sub
Sub Insert_product_codes(Value As String)
For i = 1 To UBound(Split(Value, ","))
ThisWorkbook.Sheets("Data").Cells(i, 1).Value = Split(Value, ",")(i)
Next i
End Sub
Module 1 (Containing most of the code):
Module 2 (To transpose data): Here I transpose Data from "Source Data" sheet into "Report" sheet that contains some predefined values in column A
Sub Transpose_Data()
'
' Transpose_Data Macro
'
'
Sheets("Source Data").Select
Rows("4:500").Select
Selection.Copy
Sheets("QRA Report Main").Select
Range("B4").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
Range("B6:MJ6").Select
Application.CutCopyMode = False
Selection.Insert Shift:=xlDown
Range("B12:MJ12").Select
Selection.Insert Shift:=xlDown
Selection.Insert Shift:=xlDown
Range("B17:MJ17").Select
Selection.Insert Shift:=xlDown
Selection.Insert Shift:=xlDown
Range("B23:MJ23").Select
Selection.Insert Shift:=xlDown
Selection.Insert Shift:=xlDown
Range("B28:MJ28").Select
Selection.Insert Shift:=xlDown
Selection.Insert Shift:=xlDown
Range("B36:MJ36").Select
Selection.Insert Shift:=xlDown
Selection.Insert Shift:=xlDown
Range("B45:MJ45").Select
Selection.Insert Shift:=xlDown
Selection.Insert Shift:=xlDown
Range("B51:MJ51").Select
Selection.Insert Shift:=xlDown
Selection.Insert Shift:=xlDown
Range("B54:MJ54").Select
Selection.Insert Shift:=xlDown
Selection.Insert Shift:=xlDown
Range("B61:MJ61").Select
Selection.Insert Shift:=xlDown
Selection.Insert Shift:=xlDown
Columns("B:NZ").Select
Range("B3").Activate
Selection.ColumnWidth = 30
With Selection
.HorizontalAlignment = xlRight
.WrapText = False
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
End With
ActiveWorkbook.Save
End Sub
But again as i said, I do not get exactly what I need plus, the processing time is huge.

Try this, but note you'll need to fill in the section in the middle.
``
Sub Transpose_Data()
'
' Transpose_Data Macro
'
'
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Sheets("Source Data").Rows("4:500").Copy Sheets("QRA Report Main").Range("B4")
With Sheets("QRA Report Main")
.Range("B6:MJ6").Insert Shift:=xlDown
.Range("B12:MJ12").Resize(2).Insert Shift:=xlDown
.Range("B17:MJ17").Resize(2).Insert Shift:=xlDown
.Range("B23:MJ23").Resize(2).Insert Shift:=xlDown
' add rest in here
.Range("B61:MJ61").Resize(2).Insert Shift:=xlDown
With .Columns("B:NZ")
.ColumnWidth = 30
.HorizontalAlignment = xlRight
.WrapText = False
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
End With
End With
ActiveWorkbook.Save
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
``

Related

Microsoft VBA Error - Run time Error - 1004

Run-time error '1004': The PivotTable field name is not valid. To create a PivotTable report you must use data that is organized as a list of labeled columns. If you are changing the name of a PivotTable field, you must type a new name for the field.
Here Is my Code?
Please tell me the mistake so I can understand it. also How Can I Correct it?
Option Explicit
Public PageName, RowName, ColumnName, DataName As String
Sub ShowForms()
frmGenerateReports.Show
End Sub
Sub CreatePivot()
Dim Destination, RangeData As Range
Set Destination = Worksheets("Reports").Range("A1")
Set RangeData = Range("A1", Range("I1").End(xlDown))
ActiveWorkbook.PivotCaches.Create _
(SourceType:=xlDatabase, SourceData:=RangeData) _
.CreatePivotTable TableDestination:=Destination, TableName:="SalesPivot"
End Sub
Sub SetFields()
Dim PvtTable As PivotTable
Set PvtTable = Worksheets("Reports").PivotTables("SalesPivot")
With PvtTable
.PivotFields(PageName).Orientation = xlPageField
.PivotFields(RowName).Orientation = xlRowField
.PivotFields(ColumnName).Orientation = xlColumnField
.PivotFields(DataName).Orientation = xlDataField
End With
ActiveWorkbook.Sheets("Reports").Activate
If frmGenerateReports.Sales <> "Model" Then
PvtTable.PivotSelect "", xlDataOnly
Selection.NumberFormat = "$#, ##0"
End If
Range("E1").Select
End Sub
Sub ConsolidateData(ThisMonth)
Dim BeenThere As Boolean
Dim Compare As String
Dim Sheet As Worksheet
BeenThere = False
Sheets.Add
ActiveSheet.Name = "Reports"
If frmGenerateReports.Period = "Month" Then
Select Case ThisMonth
Case "Jan"
ThisMonth = 1
Case "Feb"
ThisMonth = 2
Case "Mar"
ThisMonth = 3
Case "Apr"
ThisMonth = 4
Case "May"
ThisMonth = 5
Case "Jun"
ThisMonth = 6
Case "Jul"
ThisMonth = 7
Case "Aug"
ThisMonth = 8
Case "Sep"
ThisMonth = 9
Case "Oct"
ThisMonth = 10
Case "Nov"
ThisMonth = 11
Case "Dec"
ThisMonth = 12
End Select
End If
Select Case frmGenerateReports.Period
Case "Month"
For Each Sheet In Worksheets
Sheet.Select
Compare = ActiveSheet.Name
On Error Resume Next
Compare = Month(CDate(Compare))
If Compare = ThisMonth Then
frmGenerateReports.StartDate = Sheet.Name
If BeenThere = False Then
GrabCells 1
BeenThere = True
Else
GrabCells 2
DoEvents
End If
End If
Next
Case "All"
GrabCells 1
Do
frmGenerateReports.StartDate = frmGenerateReports.StartDate + 1
GrabCells 2
DoEvents
Loop Until frmGenerateReports.StartDate = frmGenerateReports.EndDate
Columns("A:J").EntireColumn.AutoFit
Range("A1").Select
Case "Other"
GrabCells 1
Do
frmGenerateReports.StartDate = frmGenerateReports.StartDate + 1
GrabCells 2
DoEvents
Loop Until frmGenerateReports.StartDate = frmGenerateReports.EndDate
Columns("A:J").EntireColumn.AutoFit
Range("A1").Select
End Select
End Sub
Sub GrabCells(StartingCell)
Dim CallDate, Where, Where2 As String
CallDate = Format(frmGenerateReports.StartDate, "d-mmm-yy")
Sheets(CallDate).Select
If Range("A2").Value <> Empty Then
Where = "B" & StartingCell
Where2 = "J" & StartingCell
Range(Where, Range(Where2).End(xlDown)).Select
Application.CutCopyMode = False
Selection.Copy
Range("A1").Select
Sheets("Reports").Select
ActiveSheet.Paste
Range("A1").End(xlDown).Offset(1).Select
Else
If StartingCell = 1 Then
Application.CutCopyMode = False
Range("B1:J1").Select
Selection.Copy
Sheets("Reports").Select
ActiveSheet.Paste
Range("A2").Select
End If
End If
End Sub
Sub FinishReport()
Dim Sheet As Worksheet
Workbooks.Open Filename:=ThisWorkbook.Path & "\Reports.xlsx"
For Each Sheet In Worksheets
Sheet.Select
Cells.Select
Selection.Clear
Range("A1").Select
Next
Workbooks("Sales - Fiscal Year1.xlsm").Activate
Sheets("Reports").Select
Cells.Select
Selection.Copy
Workbooks("Reports.xlsx").Activate
ActiveSheet.Paste
Range("A1").Select
Windows("Sales - Fiscal Year1.xlsm").Activate
Application.CutCopyMode = False
ActiveWindow.SelectedSheets.Delete
Workbooks("Reports.xlsx").Activate
CreatePivot
SetFields
End Sub
I need to understand the logic behind the solution and why it caused?
So that I can prevent it from happening next time.

When a number is in the cell, count it in a column that matches column header

I'm currently trying to work on a macro that will look for grades and count assignments done. It works...for the most part...But I'm having some trouble with it being very static. I've hardcoded a specific range, but I need it to be dynamic, in case more/less columns are in the spreadsheet or if columns not related to grades are added at the end (such as Finalized). My coworker may need Math/History/Science Grade 4 or 5 or 6. You get the idea.
Before macro is run:
After macro is run:
Sub CreateGrades()
Dim TempString As String
TempString = ""
Application.ScreenUpdating = False ' Ensure we aren't spamming the graphics engine
Dim TheLastRow As Long
TheLastRow = ActiveSheet.Cells(ActiveSheet.Rows.Count, "B").End(xlUp).Row
Columns("G:G").Select
Selection.Insert Shift:=xlToRight ', CopyOrigin:=xlFormatFromLeftOrAbove
Columns("H:H").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Columns("I:I").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Columns("G:G").Select
TempString = "IF(AND(ISNUMBER(RC[4]), RC[4]>0),""1,"","""")&IF(AND(ISNUMBER(RC[7]), RC[7]>0),""2,"","""")&IF(AND(ISNUMBER(RC[10]), RC[10]>0),""3,"","""")"
Selection.FormulaR1C1 = "=IF(LEN(" + TempString + ") > 0, LEFT( " + TempString + ", LEN( " + TempString + " ) - 1 ), " + TempString + " )"
Columns("G:G").EntireColumn.AutoFit
Range("G1").Select
ActiveCell.FormulaR1C1 = "Math"
Columns("H:H").Select
TempString = "IF(AND(ISNUMBER(RC[4]), RC[4]>0),""1,"","""")&IF(AND(ISNUMBER(RC[7]), RC[7]>0),""2,"","""")&IF(AND(ISNUMBER(RC[10]), RC[10]>0),""3,"","""")"
Selection.FormulaR1C1 = "=IF(LEN(" + TempString + ") > 0, LEFT( " + TempString + ", LEN( " + TempString + " ) - 1 ), " + TempString + " )"
Columns("H:H").EntireColumn.AutoFit
Range("H1").Select
ActiveCell.FormulaR1C1 = "History"
Columns("I:I").Select
TempString = "IF(AND(ISNUMBER(RC[4]), RC[4]>0),""1,"","""")&IF(AND(ISNUMBER(RC[7]), RC[7]>0),""2,"","""")&IF(AND(ISNUMBER(RC[10]), RC[10]>0),""3,"","""")"
Selection.FormulaR1C1 = "=IF(LEN(" + TempString + ") > 0, LEFT( " + TempString + ", LEN( " + TempString + " ) - 1 ), " + TempString + " )"
Columns("I:I").EntireColumn.AutoFit
Range("I1").Select
ActiveCell.FormulaR1C1 = "Science"
' Draw borders around the maps, and shade/color the cells
Call HighlightAllDataMaps(TheLastRow)
' Draw the legend at the top
Call DrawInstructions("AllData")
ActiveSheet.name = "All Grades"
' If we aren't already filtering, then turn it on
If ActiveSheet.AutoFilterMode = False Then
[a3].Select
Selection.AutoFilter
End If
Rows("1:1").Select
Selection.Activate
With Selection.Font
.ColorIndex = xlAutomatic
.TintAndShade = 0
End With
Rows("1:1").Select
With ActiveWindow
.SplitColumn = 0
.SplitRow = 1
End With
ActiveWindow.FreezePanes = True
End Sub
One idea I had was to use COUNTIFS to look for columns that have Math, Science, and History, but I know that impacts the code dramatically. I did try it with my current code, just to see if it'd work. It does work, but it took my macro 6 minutes to run! I switched out the current TempString for the following:
TempString = "IF(COUNTIFS(R1C[4],""*Math*"", RC[4], "">0""),""1,"","""")&IF(COUNTIFS(R1C[7],""*Math*"", RC[7], "">0""),""2,"","""")&IF(COUNTIFS(R1C[10],""*Math*"", RC[10], "">0""),""3,"","""")&IF(COUNTIFS(R1C[13],""*Math*"", RC[13], "">0""),""4,"","""")&IF(COUNTIFS(R1C[16],""*Math*"", RC[16], "">0""),""5,"","""")&IF(COUNTIFS(R1C[19],""*Math*"", RC[19], "">0""),""6,"","""")&IF(COUNTIFS(R1C[22],""*Math*"", RC[22], "">0""),""7,"","""")&IF(COUNTIFS(R1C[25],""*Math*"", RC[25], "">0""),""4,"","""")"
That gets around the issue of non-Grade columns getting counted, but performance really takes a hit. My mind is spent. Any help would greatly be appreciated.
When using an array equation, the processing speed becomes slow if there is a lot of data. It is better to assign values than to use formulas.
Ty,
Sub CreateGrades()
Dim TempString As String
Dim vDB As Variant, vR() As Variant
Dim rngDB As Range
Dim r As Long, i As Long
Dim j As Integer, k As Integer, n As Integer
Dim s As String
TempString = ""
'Application.ScreenUpdating = False ' Ensure we aren't spamming the graphics engine
Dim TheLastRow As Long
TheLastRow = ActiveSheet.Cells(ActiveSheet.Rows.Count, "B").End(xlUp).Row
Range("g:i").Insert
Range("g1").Resize(1, 3) = Array("Math", "History", "Science")
Set rngDB = Range("a1").CurrentRegion
vDB = rngDB
r = UBound(vDB, 1)
c = UBound(vDB, 2)
For i = 2 To r
For j = 7 To 9
n = 0
Erase vR
For k = 10 To c
If vDB(i, k) <> "" Then
s = vDB(1, k) 'Grade 1 Math or Math Grade 1
If InStr(s, vDB(1, j)) Then
s = Trim(Replace(s, vDB(1, j), ""))
n = n + 1
ReDim Preserve vR(1 To n)
vR(n) = Right(s, 1)
End If
End If
Next k
If n Then
vDB(i, j) = Join(vR, ",")
End If
Next j
Next i
rngDB = vDB
'' Draw borders around the maps, and shade/color the cells
'Call HighlightAllDataMaps(TheLastRow)
'
'' Draw the legend at the top
'Call DrawInstructions("AllData")
'
'ActiveSheet.Name = "All Grades"
'
'' If we aren't already filtering, then turn it on
'If ActiveSheet.AutoFilterMode = False Then
' [a3].Select
' Selection.AutoFilter
'End If
'
'Rows("1:1").Select
'Selection.Activate
'With Selection.Font
' .ColorIndex = xlAutomatic
' .TintAndShade = 0
'End With
'
'Rows("1:1").Select
'With ActiveWindow
' .SplitColumn = 0
' .SplitRow = 1
'End With
'ActiveWindow.FreezePanes = True
End Sub

Excel VBA Column Insertion Using Loop Function

I've got dates in Row 2 and have the following code to insert a column based on whether the date in B1 is less than the date in B2, C2, etc....
Sub Test3()
If DateValue(Cells(1, 2).Value) < DateValue(Cells(2, 2).Value) Then
Range("B2").EntireColumn.Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Cells(2, Selection.Column).Select
ActiveCell.Value = Range("B1")
ElseIf DateValue(Cells(1, 2).Value) < DateValue(Cells(2, 3).Value) Then
Range("C2").EntireColumn.Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Cells(2, Selection.Column).Select
ActiveCell.Value = Range("B1")
End If
End Sub
The above code works and adds a column at the right place and puts a date in row 2 of the column.
Obviously it would be much easier for me to loop this but I am having trouble getting the loop to work. Here is what I have so far:
Sub DateLoopTest()
Dim i As Integer
i = 1
Do Until DateValue(Cells(1, 2).Value) < DateValue(Cells(2, i + 1).Value)
Cells(2, i + 1).EntireColumn.Select
i = i + 1
Loop
ActiveCell.EntireColumn.Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Cells(2, Selection.Column).Select
ActiveCell.Value = Range("B1")
End Sub
I am getting Run-Time error '13': Type mismatch
No matter how much I mess with it I can't get it to loop like I want in my 1st example. Any suggestions
you can refer to this code:
Sub DateLoopTest()
Dim i As Integer
i = 0
'Loop from [B2] offset 0 to 1,2... -> then stop at [b2].offset(0,i)
Do Until (DateValue([b1]) < DateValue(IIf(IsDate([b2].Offset(0, i)), [b2].Offset(0, i), [b1])))
i = i + 1
Loop
[b2].Offset(0, i).EntireColumn.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
[b2].Offset(0, i).Value = [b1]
End Sub
maybe i got it wrong because i'm just looking at your code, try this again, hope it helps :)
Sub DateLoopTest1()
Dim i As Integer, isCellhere As Boolean, isExistCell As Boolean, isRecentday As Boolean: i = 0:
isRecentday = True
'get lastCell index for Loop
Dim iLast As Integer: iLast = Cells(2, 15000).End(xlToLeft).Column
Dim iMax As Integer: iMax = 2 'default
Dim Cellmax As Range: Set Cellmax = [b2] 'default
Dim Datedefault As Variant: Datedefault = #1/1/1000#
If iLast = 1 Then Exit Sub
'Loop until CellMax
For i = 0 To iLast - 2
isCellhere = Datedefault < DateValue(IIf(IsDate([b2].Offset(0, i)), [b2].Offset(0, i), Datedefault))
'stop if True
If isCellhere Then Set Cellmax = [b2].Offset(0, i): Datedefault = DateValue([b2].Offset(0, i).Value)
Next i
Cellmax.EntireColumn.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Cellmax.Offset(0, -1).Value = [b1]
End Sub

End vba code if no value found

I am using this code to transfer data from one sheet to another. The code allows for the data being transferred to stay on the new sheet until deleted.
Private Sub Transfer2_Click()
Dim Work_Order1 As String, Qty1 As Integer, Frame1 As String, Qty_Frame1 As Integer
Worksheets("Work_Order").Select
if Worksheets("Work_Order").Range("C12") = "" Then Exit Sub
Work_Order1 = Range("N3")
Qty1 = Range("B3")
Frame1 = Range("C12").Value
Qty_Frame1 = Range("M12")
Worksheets("Order").Select
Worksheets("Order").Range("A4").Select
If Worksheets("Order").Range("A4").Offset(1, 0) <> "" Then
Worksheets("Order").Range("A4").End(xlDown).Select
End If
ActiveCell.Offset(1, 0).Select
ActiveCell.Value = Work_Order1
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = Qty1
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = Frame1
ActiveCell.Offset(0, 2).Select
ActiveCell.Value = Qty_Frame1
Private Sub Transfer2_Click()
Dim Work_Order2 As String, Qty2 As Integer, Frame2 As String, Qty_Frame2 As Integer
Worksheets("Work_Order").Select
if Worksheets("Work_Order").Range("C13") = "" Then Exit Sub
Work_Order2 = Range("N3")
Qty2 = Range("B3")
Frame2 = Range("C13").Value
Qty_Frame2 = Range("M13")
Worksheets("Order").Select
Worksheets("Order").Range("A4").Select
If Worksheets("Order").Range("A4").Offset(1, 0) <> "" Then
Worksheets("Order").Range("A4").End(xlDown).Select
End If
ActiveCell.Offset(1, 0).Select
ActiveCell.Value = Work_Order2
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = Qty2
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = Frame2
ActiveCell.Offset(0, 2).Select
ActiveCell.Value = Qty_Frame2
Private Sub Transfer2_Click()
Dim Work_Order3 As String, Qty3 As Integer, Frame3 As String, Qty_Frame3 As Integer
Worksheets("Work_Order").Select
if Worksheets("Work_Order").Range("C14") = "" Then Exit Sub
Work_Order1 = Range("N3")
Qty3 = Range("B3")
Frame3 = Range("C14").Value
Qty_Frame3 = Range("M14")
Worksheets("Order").Select
Worksheets("Order").Range("A4").Select
If Worksheets("Order").Range("A4").Offset(1, 0) <> "" Then
Worksheets("Order").Range("A4").End(xlDown).Select
End If
ActiveCell.Offset(1, 0).Select
ActiveCell.Value = Work_Order3
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = Qty3
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = Frame3
ActiveCell.Offset(0, 2).Select
ActiveCell.Value = Qty_Frame3
What I am trying to do is end this code is no value is found in the "C" Range. I have the code repeated nine times because there are nine instances where this info can be found, but not all will have values all the time. If that occurs, I want it to end the code before transferring info to the new sheet.
so far I've tried:
if Worksheets("Work_Order").Range("C12")="" Then
Exit sub
But it returns with the error Block if without end if.
By putting the Exit Sub on a different line to the If, you are creating a "Block If", which needs an End If:
If Worksheets("Work_Order").Range("C12")="" Then
Exit sub
End If
If you want to use a "single-line If", you should put your statements on a single line:
If Worksheets("Work_Order").Range("C12")="" Then Exit sub
Both statements work in exactly the same way, but "block Ifs" are usually easier to code when you have multiple statements to be executed within either the True or False leg of the statement.
E.g.
If a = 5 Then
b = 7
c = 10 * a - b
d = 5 + b - c
Else
b = 9
c = 20 * a - 4 * b
d = 6 + b + c
End If
is easier to read than
If a = 5 Then b = 7: c = 10 * a - b: d = 5 + b - c Else b = 9: c = 20 * a - 4 * b: d = 6 + b + c
In response to your comments, I am guessing that you don't actually want to Exit Sub when you hit a blank value, you want to instead go on to process the next range.
This could be done like this:
Private Sub Transfer2_Click()
Dim Work_Order1 As String, Qty1 As Integer, Frame1 As String, Qty_Frame1 As Integer
If Worksheets("Work_Order").Range("C12").Value <> "" Then
Worksheets("Work_Order").Select
Work_Order1 = Range("N3")
Qty1 = Range("B3")
Frame1 = Range("C12").Value
Qty_Frame1 = Range("M12")
Worksheets("Order").Select
Worksheets("Order").Range("A4").Select
If Worksheets("Order").Range("A4").Offset(1, 0) <> "" Then
Worksheets("Order").Range("A4").End(xlDown).Select
End If
ActiveCell.Offset(1, 0).Select
ActiveCell.Value = Work_Order1
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = Qty1
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = Frame1
ActiveCell.Offset(0, 2).Select
ActiveCell.Value = Qty_Frame1
End If
'Then repeat for the next set of cells
which can be rewritten to avoid the use of Select (which leads to so many problems) as
Private Sub Transfer2_Click()
Dim Work_Order1 As String, Qty1 As Integer, Frame1 As String, Qty_Frame1 As Integer
If Worksheets("Work_Order").Range("C12").Value <> "" Then
With Worksheets("Work_Order")
Work_Order1 = .Range("N3")
Qty1 = .Range("B3")
Frame1 = .Range("C12").Value
Qty_Frame1 = .Range("M12")
End With
With Worksheets("Order").Cells(Worksheets("Order").Rows.Count, "A").End(xlUp).Offset(1, 0).EntireRow
.Cells(1, "A").Value = Work_Order1
.Cells(1, "B").Value = Qty1
.Cells(1, "C").Value = Frame1
.Cells(1, "E").Value = Qty_Frame1
End With
End If
'Then repeat for the next set of cells
But it would be best if that was split into two subroutines to avoid a lot of repetitive code:
Private Sub Transfer2_Click()
With Worksheets("Work_Order")
Transfer2_Paste .Range("N3").Value, .Range("B3").Value, .Range("C12").Value, .Range("M12").Value
'Then repeat for the next set of cells, e.g.
'Transfer2_Paste .Range("N4").Value, .Range("B4").Value, .Range("C13").Value, .Range("M13").Value
'etc
End With
End Sub
Private Sub Transfer2_Paste(Work_Order1 As String, Qty1 As Integer, Frame1 As String, Qty_Frame1 As Integer)
If Frame1 = "" Then
Exit Sub
End If
With Worksheets("Order").Cells(Worksheets("Order").Rows.Count, "A").End(xlUp).Offset(1, 0).EntireRow
.Cells(1, "A").Value = Work_Order1
.Cells(1, "B").Value = Qty1
.Cells(1, "C").Value = Frame1
.Cells(1, "E").Value = Qty_Frame1
End With
End Sub

Visual Basic Excel Macro MessageBox.Show Throws "Object Required" Error

Simply put no matter how hard I try I cannot get a MessageBox to appear through my Excel macro.
Here is the line I have so far:
MyBox = MessageBox.Show("Stuff", "Title")
When I run this macro I get the following error:
Run-time error '424':
Object required
What's going on!?!?
Here is the complete code:
Sub ImportParser()
'
' ImportParser Macro
' By: Dennis Plotnik (July 2013)
'
Dim ToKeepSize As Integer ' Size of ToKeep array
Dim BlankCount As Integer ' Counts blank lines so as to stop execution after EOF
Dim ReqText As String ' Required String
ReqText = "Import Control"
BlankCount = 0
ToKeepSize = -1
' Dim ToKeep As String()
Dim ToKeep() As String ' Array to store names of tables that include required text
Dim CurrentTable As String ' String to store last required table name
Range("B1").Select
Do
Do ' Go down until come to non-blank row (or exit if all blank)
Selection.Offset(1, 0).Select
Dim tempS As String
tempS = "'" + ActiveCell.Formula
ActiveCell.Value = tempS
If ActiveCell.Value = "" Then
BlankCount = BlankCount + 1
Else
Exit Do
End If
Loop Until BlankCount > 15
If InStr(1, ActiveCell.Value, ReqText, vbTextCompare) > 0 Then ' Check for ReqText in current cell
' ActiveCell.Value = "HELLO!" ' For DEBUG purposes
ToKeepSize = ToKeepSize + 1 ' Increment size of array (to allow for new value)
ReDim Preserve ToKeep(ToKeepSize)
Selection.Offset(0, -1).Select ' Move left to retrieve name of table (category)
CurrentTable = ActiveCell.Value
ToKeep(ToKeepSize) = CurrentTable
For j = 0 To 10000
Selection.Offset(1, 0).Select ' Cycle down until new table is reached
Do
If ActiveCell.Value = "" Then
BlankCount = BlankCount + 1
Selection.Offset(1, 0).Select
Else
Exit Do
End If
Loop Until BlankCount > 15
If ActiveCell.Value <> CurrentTable Then
Selection.Offset(-1, 1).Select ' Return to Field Name to continue search for ReqText
Exit For
End If
Next j
End If
Loop Until BlankCount > 15
' Range("F1").Select ' Print found tables [FOR DEBUG]
' For i = 0 To ToKeepSize
' ActiveCell.Value = ToKeep(i)
' Selection.Offset(1, 0).Select
' Next i
' ActiveCell.Value = CStr(ToKeepSize)
For i = 0 To 1 ' Prepare Table for Flag Columns
Range("A1").EntireColumn.Insert
Next i
Range("A1").Select
ActiveCell.Value = "Import Controlled?"
Range("B1").Select
ActiveCell.Value = "Delete it?"
Columns("A:F").AutoFit
BlankCount = 0
Dim ImportControl As Boolean
ImportControl = False
Range("C1").Select
Do ' Flag necessary columns
Selection.Offset(1, 0).Select
If ActiveCell.Value = "" Then
BlankCount = BlankCount + 1
Else
For i = 0 To ToKeepSize
If ActiveCell.Value = ToKeep(i) Then
Selection.Offset(0, -2).Value = 1
Exit For
End If
Next i
End If
Loop Until BlankCount > 15
Range("A1").Select ' Sort to push all required tables to top of file
Columns("A:A").Select
ActiveSheet.Sort.SortFields.Clear
ActiveSheet.Sort.SortFields.Add Key:=Range("A1"), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveSheet.Sort
.SetRange Range("A:F")
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Range("A1").Select
Do
Selection.Offset(1, 0).Select
Loop Until ActiveCell.Value = ""
MyBox = MessageBox.Show("Stuff", "Title")
Dim file As String
file = Application.ActiveWorkbook.Path
Dim Word As Object: Set Word = CreateObject("Word.Application")
Word.Visible = True
Set docWD = Word.Documents.Add
docWD.SaveAs file & "\" & "dictionary", FileFormat:=wdFormatDocument
Range(ActiveCell.Offset(0, 2), "F1").Copy
Word.Selection.Paste
End Sub
MessageBox.Show is VB.Net. Even though you have tagged it as VB.Net, I believe you are doing this in VBA.
Try this
MyBox = MsgBox("Stuff", vbInformation, "Title")

Resources