I have code that open's up an excel file used for mapping data. Then opens up a transaction file and appends columns to the file based on the mapping data. It works however I am having speed issues, it runs slow. If I click and hold the scroll bar in Excel it speeds up but when I let up the mouse button it slows back down, thoughts?
Dim MapLocation As String
Dim MapHeader As Integer
Dim MapColumnLegacy As Integer
Dim MapColumnFE As Integer
Dim MapColumnClass As Integer
Dim MapColumnProject As Integer
Dim MapColumnTcode1 As Integer
Dim MapColumnTcode2 As Integer
Dim MapColumnTcode3 As Integer
Dim MapColumnTcode4 As Integer
Dim MapColumnTcode5 As Integer
'Dim MapLines As Integer
Dim TransLocation As String
Dim TransHeader As Integer
Dim TransLines As Integer
Dim TransColumnLegacy As Integer
Dim ConvertSheet As Integer
Dim Xl As New Excel.Application
Dim Xlsheet As Excel.Worksheet
Dim Xlwbook As Excel.Workbook
Dim OldAcctID() As String
Dim NewAcctID() As String
Dim NewProjID() As String
Dim NewClassID() As String
Dim NewTcode1ID() As String
Dim NewTcode2ID() As String
Dim NewTcode3ID() As String
Dim NewTcode4ID() As String
Dim NewTcode5ID() As String
Dim I As Integer
Dim J As Integer
Dim Sheet As Object
Sub AcctConv_Main()
Call Cleanup
Call File_Access
Call OpenExcelfile
End Sub
Sub Cleanup()
ReDim OldAcctID(TransLines) As String
ReDim NewAcctID(TransLines) As String
ReDim NewProjID(TransLines) As String
ReDim NewClassID(TransLines) As String
ReDim NewTcode1ID(TransLines) As String
ReDim NewTcode2ID(TransLines) As String
ReDim NewTcode3ID(TransLines) As String
ReDim NewTcode4ID(TransLines) As String
ReDim NewTcode5ID(TransLines) As String
I = 1
For I = 1 To TransLines
OldAcctID(I) = ""
NewAcctID(I) = ""
Next I
End Sub
Sub File_Access()
' Open Account Mapping and input the data from
' columns which contain the old and
' new data for the account mappings
'
If MapHeader = 0 Then
I = 1
Else: I = 2
End If
Xl.Workbooks.Open MapLocation
Xl.ActiveWorkbook.RunAutoMacros xlAutoOpen
For I = 1 To TransLines
OldAcctID(I) = Cells(I, MapColumnLegacy)
NewAcctID(I) = Cells(I, MapColumnFE)
If Config_Form.MapProject_Check.Value = 1 Then
NewProjID(I) = Cells(I, MapColumnProject)
End If
If Config_Form.MapClass_Check.Value = 1 Then
NewClassID(I) = Cells(I, MapColumnClass)
End If
If Config_Form.MapTcode1_Check.Value = 1 Then
NewTcode1ID(I) = Cells(I, MapColumnTcode1)
End If
If Config_Form.MapTcode2_Check.Value = 1 Then
NewTcode2ID(I) = Cells(I, MapColumnTcode2)
End If
If Config_Form.MapTcode3_Check.Value = 1 Then
NewTcode3ID(I) = Cells(I, MapColumnTcode3)
End If
If Config_Form.MapTcode4_Check.Value = 1 Then
NewTcode4ID(I) = Cells(I, MapColumnTcode4)
End If
If Config_Form.MapTcode5_Check.Value = 1 Then
NewTcode5ID(I) = Cells(I, MapColumnTcode5)
End If
Next I
Xl.ActiveWorkbook.Close False
Xl.Quit
End Sub
Sub OpenExcelfile()
Xl.Workbooks.Open (TransLocation)
ActiveWorkbook.Sheets(ConvertSheet).Activate
Xl.Visible = True
'Opens transaction document to insert columns
Call LegacyAttribute
'Insert a new Column for Attribute and renames it, renames Legacy account header as Attribute Type
Call InsertNewAccount
'Insert a new Column for FE account and renames it
Call InsertNewProject
'Insert a new Column for Project and renames it
Call InsertNewClass
'Insert a new Column for Class and renames it
Call InsertNewTcode1
'Insert a new Column for Tcode1 and renames it
Call InsertNewTcode2
'Insert a new Column for Tcode2 and renames it
Call InsertNewTcode3
'Insert a new Column for Tcode3 and renames it
Call InsertNewTcode4
'Insert a new Column for Tcode4 and renames it
Call InsertNewTcode5
'Insert a new Column for Tcode5 and renames it
Call PlugInNewAcctIDs
'save the file
Xl.ActiveWorkbook.Save
'close the file
Xl.ActiveWorkbook.Close
Xl.Quit
Convertwait_Form.Hide
Unload Convertwait_Form
MsgBox "Your Accounts Have Been Converted", vbExclamation, "Conversion Complete"
'get the next file
End Sub
Sub PlugInNewAcctIDs()
' Go back to the main XL document and
' plug in the new account numbers when a match
' to the old number is found in the first column
'
Convertwait_Form.Show
BadCell = Cells(I, 2)
I = 1
J = 1
For I = 1 To TransLines
If (Cells(I, 1) = "") And (Cells(I + 1, 1) = "") And (Cells(I + 2, 1) = "")Then
GoTo Continue
Else
For J = 1 To TransLines
If Cells(I, 1) = OldAcctID(J) Then
Cells(I, 2) = "Legacy Account"
Cells(I, 3) = NewAcctID(J)
If Config_Form.MapProject_Check.Value = 1 Then
Cells(I, 4) = NewProjID(J)
End If
If Config_Form.MapClass_Check.Value = 1 Then
Cells(I, 5) = NewClassID(J)
End If
If Config_Form.MapTcode1_Check.Value = 1 Then
Cells(I, 6) = NewTcode1ID(J)
End If
If Config_Form.MapTcode2_Check.Value = 1 Then
Cells(I, 7) = NewTcode2ID(J)
End If
If Config_Form.MapTcode3_Check.Value = 1 Then
Cells(I, 8) = NewTcode3ID(J)
End If
If Config_Form.MapTcode4_Check.Value = 1 Then
Cells(I, 9) = NewTcode4ID(J)
End If
If Config_Form.MapTcode5_Check.Value = 1 Then
Cells(I, 10) = NewTcode5ID(J)
End If
End If
If Cells(I, 3) = "" Then
Cells(I, 3) = "Missing Account Mapping"
End If
Next J
End If
If Cells(I, 3) = "Missing Account Mapping" Then
Cells(I, 3).Interior.ColorIndex = 44
Cells(I, 3).Font.Color = vbRed
End If
Next I
Continue:
End Sub
Here is how to do what is recommended in the comments...
Change your AcctConv_Main() routine to this:
Sub AcctConv_Main()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Call CleanUp
Call File_Access
Call OpenExcelfile
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
Related
I try to work on a Project but it seems that it's far from my ability.
I need to Compare 2 workbooks containing 3 sheets ("WireList", "Cumulated BOM" and "BOM"), when I Browse File 1 and File 2 all sheets should compare at the same time and give the result in the format below:
I try a lot of codes but I am still a beginner and I hope if possible someone can help
Thank you very Much
Code Examples 1 : (Just to compare)
Option Explicit
Sub Compare()
'Define Object for Excel Workbooks to Compare
Dim sh As Integer, shName As String
Dim F1_Workbook As Workbook, F2_Workbook As Workbook
Dim iRow As Double, iCol As Double, iRow_Max As Double, iCol_Max As Double
Dim File1_Path As String, File2_Path As String, F1_Data As String, F2_Data As String
'Assign the Workbook File Name along with its Path
File1_Path = ThisWorkbook.Sheets(1).Cells(1, 2)
File2_Path = ThisWorkbook.Sheets(1).Cells(2, 2)
iRow_Max = ThisWorkbook.Sheets(1).Cells(3, 2)
iCol_Max = ThisWorkbook.Sheets(1).Cells(4, 2)
Set F2_Workbook = Workbooks.Open(File2_Path)
Set F1_Workbook = Workbooks.Open(File1_Path)
ThisWorkbook.Sheets(1).Cells(6, 2) = F1_Workbook.Sheets.Count
'With F1_Workbook object, now it is possible to pull any data from it
'Read Data From Each Sheets of Both Excel Files & Compare Data
For sh = 1 To F1_Workbook.Sheets.Count
shName = F1_Workbook.Sheets(sh).Name
ThisWorkbook.Sheets(1).Cells(7 + sh, 1) = shName
ThisWorkbook.Sheets(1).Cells(7 + sh, 2) = "Identical Sheets"
ThisWorkbook.Sheets(1).Cells(7 + sh, 2).Interior.Color = vbGreen
For iRow = 1 To iRow_Max
For iCol = 1 To iCol_Max
F1_Data = F1_Workbook.Sheets(shName).Cells(iRow, iCol)
F2_Data = F2_Workbook.Sheets(shName).Cells(iRow, iCol)
'Compare Data From Excel Sheets & Highlight the Mismatches
If F1_Data <> F2_Data Then
F1_Workbook.Sheets(shName).Cells(iRow, iCol).Interior.Color = vbYellow
ThisWorkbook.Sheets(1).Cells(7 + sh, 2) = "Mismatch Found"
ThisWorkbook.Sheets(1).Cells(7 + sh, 2).Interior.Color = vbYellow
End If
Next iCol
Next iRow
Next sh
'Process Completed
ThisWorkbook.Sheets(1).Activate
MsgBox "Task Completed - Thanks for Visiting OfficeTricks.Com"
End Sub
Code Example 2 :
Option Explicit
Sub test_CompareSheets_Adv()
ActiveWorkbook.Activate
If SheetExists("results") = False Then
Sheets.Add
ActiveSheet.Name = "results"
End If
If CompareSheets_Adv("Sheet3", "Sheet4") = True Then
MsgBox " Completed Successfully!"
Else
MsgBox "Process Failed"
End If
End Sub
Function CompareSheets_Adv(sh1Name$, sheet2name$) As Boolean
Dim vstr As String
Dim vData As Variant
Dim vitm As Variant
Dim vArr As Variant
Dim v()
Dim a As Long
Dim b As Long
Dim c As Long
On Error GoTo CompareSheetsERR
vData = Sheets(sh1Name$).Range("A1:T6817").Value
With CreateObject("Scripting.Dictionary")
.CompareMode = 1
ReDim v(1 To UBound(vData, 2))
For a = 2 To UBound(vData, 1)
For b = 1 To UBound(vData, 2)
vstr = vstr & Chr(2) & vData(a, b)
v(b) = vData(a, b)
Next
.Item(vstr) = v
vstr = ""
Next
vData = Sheets(sheet2name$).Range("A1:T6817").Value
For a = 2 To UBound(vData, 1)
For b = 1 To UBound(vData, 2)
vstr = vstr & Chr(2) & vData(a, b)
v(b) = vData(a, b)
Next
If .exists(vstr) Then
.Item(vstr) = Empty
Else
.Item(vstr) = v
End If
vstr = ""
Next
For Each vitm In .keys
If IsEmpty(.Item(vitm)) Then
.Remove vitm
End If
Next
vArr = .items
c = .Count
End With
With Sheets("Results").Range("a1").Resize(, UBound(vData, 2))
.Cells.Clear
.Value = vData
If c > 0 Then
.Offset(1).Resize(c).Value = Application.Transpose(Application.Transpose(vArr))
End If
End With
CompareSheets_Adv = True
Exit Function
CompareSheetsERR:
CompareSheets_Adv = False
End Function
Function SheetExists(shName As String) As Boolean
With ActiveWorkbook
On Error Resume Next
SheetExists = (.Sheets(shName).Name = shName)
On Error GoTo 0
End With
End Function
I am relatively new to this coding. I am trying to add to my inventory database(in another sheet) if the model that is key into the activex textbox dose not match. If it matches, then it will automatically update to the quantity. However, I am getting error438. Here is the code that I have written so far.
Sub Add()
Dim invdata As Worksheet
Dim frm As Worksheet
Dim iqty As Integer
Set frm = ThisWorkbook.Sheets("UserForm")
Set invdata = ThisWorkbook.Sheets("Inventory Database")
iqty = frm.Range("B9")
Dim irow As Integer
Dim jrow As Integer
Dim i As Integer
If Application.WorksheetFunction.CountIf(invdata.Range("C:C"), ActiveSheet.tbModel.Value) > 0 Then
jrow = invdata.Range("A" & invdata.Rows.Count).End(xlUp).row + 1
With invdata
.Cells(jrow, 1).Value = frm.Range("B6").Value
.Cells(jrow, 2).Value = frm.Range("B7").Value
.Cells(jrow, 3).Value = ActiveSheet.tbModel.Value
.Cells(jrow, 4).Value = frm.Range("B9").Value
End With
MsgBox ("New Model Added!")
Else
irow = invdata.Cells(Rows.Count, 3).End(xlUp).row
For i = 2 To irow
If Sheet1.Cells(i, 3) = ActiveSheet.tbModel.Value Then
Sheet1.Cells(i, 4) = Sheet1.Cells(i, 4) + iqty
Exit Sub
End If
Next i
End If
End Sub
Try this - using Find() instead of CountIf() saves you from the loop:
Sub Add()
Dim invdata As Worksheet, frm As Worksheet, model, f As Range
Dim iqty As Long
Set frm = ThisWorkbook.Sheets("UserForm")
Set invdata = ThisWorkbook.Sheets("Inventory Database")
iqty = frm.Range("B9").Value
model = frm.OLEObjects("tbModel").Object.Value '####
'see if there's a match using `Find()`
Set f = invdata.Range("C:C").Find(what:=model, lookat:=xlWhole)
If f Is Nothing Then
'model was not found in Col C
With invdata.Range("A" & invdata.Rows.Count).End(xlUp).Offset(1)
.Value = frm.Range("B6").Value
.Offset(0, 1).Value = frm.Range("B7").Value
.Offset(0, 2).Value = model
.Offset(0, 3).Value = iqty
End With
MsgBox "New Model Added!"
Else
With f.EntireRow.Cells(4)
.Value = .Value + iqty ' update qty in row `m`
End With
End If
End Sub
I have multiple worksheets and each sheet contains skill details.
Sample data
Skills Name
Programs(C#, VB, Python) C#
OS(Windows, Linux)
DB(Oracle, SQL) Oracle
My requirement is, if user put skills as "Programs(C#, VB, Python)", then return next cell value i.e. "C#"
My code.
Private Sub BtnReport_Click()
Dim SkillName As String
Dim SkillRng As Range
Dim rng As Range
'Dim nextblankrow As Long
'Dim lastrow As Long
Dim x As Long
Dim y As Long
Dim val As String
SkillName = ActiveWorkbook.Worksheets("Admin").Range("L4")
If SkillName = "" Then
MsgBox "Select a skill name"
Exit Sub
End If
'Sheets(2).Select
'Set rng = Sheets(2).Range("B14:B100").Find(What:=SkillName)
'MsgBox rng.Value
Sheets("Report").Select
Sheets("Report").Cells.ClearContents
Sheets("Report").Cells(1, 1) = "Skill Name"
Sheets("Report").Cells(1, 2) = "Resource"
'''''For i = 1 To Sheets.Count - 1
''''' Set rng = Sheets(i).Range("B14:C100")
''''' Set SkillRng = rng.Find(What:=SkillName)
''''' If Not SkillRng Is Nothing Then
''''' Sheets("Report").Cells(i + 1, 1) = SkillRng.Value
''''' MsgBox rng.Cells.Value
'''''' Sheets("Report").Cells(i + 1, 2) = rng.Offset(RowoffSet = 1, Columnoffset = 2).Value
'''''' Sheets("Report").Cells(i + 1, 2) = SkillRng.Cells(Selection.Row, Selection.Column + 1).Value
''''' Sheets("Report").Cells(i + 1, 3) = ActiveWorkbook.Worksheets(i).name
''''' End If
'''''Next i
Set rng = Sheets(2).Range("B14:C100")
Set SkillRng = rng.Find(What:=SkillName)
For x = 1 To rng.Rows.Count
For y = 1 To rng.Columns.Count
If rng.Cells(x, y) = SkillRng Then
' Sheets("Report").Cells(2, 2) = rng.Cells(x, y + 1)
MsgBox SkillRng
MsgBox x
MsgBox y
val = Cells(x, y).Value
' val = SkillRng
MsgBox val
End If
Next y
Next x
I believe this will give you everything with little editing for sheet numbers and intended Report cell values
There is difference between sheets and worksheets. Sheets also include charts. So for your purpose use worksheets. Also, you have to skip the Report and Admin Worksheets for evaluation in the loop. If your report and Admin worksheets are (1) and (2) then start loop from 3. If you loop also evaluates these sheets and if it finds skillname in range to find (rng) in these sheets values from these sheets will also appear in your report.
Private Sub BtnReport_Click()
Dim SkillName As String
Dim SkillRng As Range
Dim rng As Range
SkillName = ActiveWorkbook.Worksheets("Admin").Range("L4")
If SkillName = "" Then
MsgBox "Select a skill name"
Exit Sub
End If
Sheets("Report").Select
Sheets("Report").Cells.ClearContents
Sheets("Report").Cells(1, 1) = "Skill Name"
Sheets("Report").Cells(1, 2) = "Resource"
For i = 1 To Worksheets.Count
Set rng = Worksheets(i).Range("B14:C100")
Set SkillRng = rng.Find(What:=SkillName)
k = Sheets("Report").Range("A1").CurrentRegion.Rows.Count + 1
If Not SkillRng Is Nothing Then
Sheets("Report").Cells(k, 1) = SkillName
Sheets("Report").Cells(k, 2) = SkillRng.Value
Sheets("Report").Cells(k, 3) = SkillRng.offset(0,1)
Sheets("Report").Cells(k, 4) = Worksheets(i).name
End If
Next i
End sub
Public Sub caInvCompressRows(p_strInv As String)
Dim intRow As Integer
Dim intRowMch As Integer
Dim intCol As Integer
Dim bUsed As Boolean
Dim strTemp As String
Dim strSheet As String
Dim intSaveRow As Integer
strSheet = "cordINV-" & p_strInv
Call utlUnProtectSheet(strSheet, "alcatraz")
Sheets(strSheet).Select
Cells.Select
Rows.EntireRow.Hidden = False
Range("A1").Select
intRowMch = caINV_ROW_FIRST
While Cells(intRowMch, 1).Value <> "" Or Cells(intRowMch, 11).Value <> ""
For intRow = intRowMch + 1 To intRowMch + 6
If Cells(intRow, 1).Value = "" Then
If Cells(intRow, 11).Value = "" Then
Rows(intRow).EntireRow.Hidden = True
End If
End If
Next intRow
intRowMch = intRowMch + 9
Wend
End Sub
I want to hide rows that don't have data in them with the use of a button. each row contains three different groups of data that change which rows would need to be hidden. all data is pulled into columns C, O and AC and the rest is populated from that.
This formula checks if there is anything in row 2, simply by concatenating the whole row, trimming the result, and check if it is nothing but an empty string:
=TRIM(TEXTJOIN("";FALSE;2:2))=""
Sub HideRows()
If Range("d2").Value = "" Then
If Range("r2").Value = "" Then
If Range("af2").Value = "" Then
Rows("2:2").EntireRow.Hidden = True
End If
End If
End If
End Sub
Excel spreadsheet
I have a set of over 10,000 lines of text strings in column A (Input), and I need to get the number (in case there is only one) or a sum of both (in case there are two).
Code
Here is the VBA code I have:
Sub ExtractNumericStrings()
Dim rngTemp As Range
Dim strTemp As String
Dim currNumber1 As Currency
Dim currNumber2 As Currency
Dim lngTemp As Long
Dim lngPos As Long
Dim lngLastRow As Long
With ActiveSheet
lngLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For Each rngTemp In .Cells(1, "A").Resize(lngLastRow, 1) ' Set Range to look at
strTemp = rngTemp.Value2 ' Get string value of each cell
lngTemp = Len(strTemp) 'Get length of string
currNumber1 = 0 ' Reset value
currNumber2 = 0 ' Reset value
' Get first number
currNumber1 = fncGetNumericValue(strTemp, 1) ' Strip out first number
' Get second number if exists
' First strip out first number
strTemp = Replace(strTemp, currNumber1, "")
If Len(strTemp) <> 0 Then
currNumber2 = fncGetNumericValue(strTemp, 1)
End If
' now paste to sheet
If currNumber1 <> 0 And currNumber2 <> 0 Then
rngTemp.Offset(0, 1).Value = currNumber1 + currNumber2
rngTemp.Offset(0, 2).Value = "sum of the numbers"
ElseIf currNumber1 <> 0 Then
rngTemp.Offset(0, 1).Value = currNumber1
End If
Next rngTemp
End With
Call MsgBox("Procedure Complete!", vbOKOnly + vbInformation, "Procedure Complete")
End Sub
Private Function fncGetNumericValue(strTemp As String, lngStart As Long) As Currency
Dim varTemp As Variant
Dim lngCount As Long
Dim lngTemp As Long
' Reset
lngCount = 1
lngTemp = 1
varTemp = ""
On Error Resume Next
If IsNumeric(Left(strTemp, lngCount)) Then
Do While IsNumeric(Left(strTemp, lngCount)) = True
varTemp = Left(strTemp, lngCount)
lngCount = lngCount + 1
If lngCount > Len(strTemp) Then
Exit Do
End If
Loop
Else
' First clear non-numerics from string
lngTemp = 1
Do While IsNumeric(Left(strTemp, 1)) = False
lngTemp = lngTemp + 1
strTemp = Mid(strTemp, 2, Len(strTemp) - 1)
If lngTemp > Len(strTemp) Then
Exit Do
End If
Loop
' Then extract second number if exists
If strTemp <> "" Then
Do While IsNumeric(Mid(strTemp, lngCount, 1)) = True
varTemp = Left(strTemp, lngCount)
lngCount = lngCount + 1
If lngCount > Len(strTemp) Then
Exit Do
End If
Loop
End If
End If
' Retrun Value
If IsNumeric(varTemp) Then
fncGetNumericValue = CCur(varTemp)
Else
fncGetNumericValue = 0
End If
End Function
Here is what I'm trying to do:
https://www.youtube.com/watch?v=EjHnJVxuWJA
I have very limited knowledge of VBA, so please excuse me if I ask any stupid question. Running this thing successfully will save me hips of time. thanks!
Something like this:
Private Sub extract_num()
Dim cell as Range
Dim ws as Worksheet: Set ws = Sheets("Sheet1") ' replace Sheet1 with ur sheet name
Dim lr as Long: Set lr = ws.Cells(Rows.Count, 1).End(xlUp).Row
Dim values() As String
Dim i as Byte
Dim temp as Double
For Each cell in ws.Range("A2:A" & lr)
If Not isEmpty(cell) Then
values = Split(cell, " ")
For i = LBound(values) to UBound(values)
values(i) = Replace(values(i), ",", ".")
If isNumeric(values(i)) Then
temp = temp + values(i)
End If
Next i
cell.Offset(0, 2) = temp
temp = 0
End If
Next cell
End Function
This is presuming:
a) Individual words and numbers are always separated by space "123 abc 321"
b) Commas "," are used as an arithmetic floatpoint separator ##,##
Slightly different approach from Rawrplus
Option Explicit
Sub UpdateTotals()
Dim aRawValues As Variant
Dim iLRow&, iRow&, iArr&
Dim dTotal#
With ThisWorkbook.Worksheets("Sheet1") '<-- Change the sheet name to your sheet
iLRow = .Cells(Rows.Count, 1).End(xlUp).Row ' Get row count
For iRow = 1 To iLRow ' Loop through all rows in the sheet
aRawValues = Split(.Range("A" & iRow).Value, " ") ' Create and array of current cell value
For iArr = LBound(aRawValues) To UBound(aRawValues) ' Loop through all values in the array
dTotal = dTotal + ReturnDouble(Replace(aRawValues(iArr), ",", ".")) ' Add the returned double to total
Next
.Range("B" & iRow).Value = dTotal ' Set value in column B
dTotal = 0# ' Reset total
Next
End With
End Sub
Function ReturnDouble(ByVal sTextToConvert As String) As Double
Dim iCount%
Dim sNumbers$, sCurrChr$
sNumbers = ""
For iCount = 1 To Len(sTextToConvert)
sCurrChr = Mid(sTextToConvert, iCount, 1)
If IsNumeric(sCurrChr) Or sCurrChr = "." Then
sNumbers = sNumbers & sCurrChr
End If
Next
If Len(sNumbers) > 0 Then
ReturnDouble = CDbl(sNumbers)
Else
ReturnDouble = 0#
End If
End Function