What I am trying to do is pass an interger argument between Auto Update & Update so that each time For RowNumber goes up by one that it stores that value in Auto Update and then closes and reopens Update which then continues counting RowNumber where it left off. This is what I have so far. How do I get the Panel.xls to open and close?
Public RowNumber As Integer
Public LoopCount As Integer
Sub auto_open()
Application.DisplayAlerts = False
Application.ScreenUpdating = False
Application.PrintCommunication = False
Dim PanelFilePath As String
Dim PanelFileName As String
Dim PanelLocation As String
Dim PanelWB As Workbook
PanelFilePath = "D:\umc\UMC Production Files\Automation Files\"
PanelFileName = "Panel.xls"
PanelLocation = PanelFilePath & Dir$(PanelFilePath & PanelFileName)
RowNumber = 0
For LoopCount = 0 To 7
If LoopCount < 7 Then
Set PanelWB = Workbooks.Open(Filename:=PanelLocation, UpdateLinks:=3)
PanelWB.RunAutoMacros Which:=xlAutoOpen
Application.Run "Panel.xls!Update"
PanelWB.Close
End If
Next LoopCount
Call Shell("D:\umc\UMC Production Files\Automation Files\Auto.bat", vbNormalFocus)
Application.Quit
Application.DisplayAlerts = True
Application.ScreenUpdating = True
Application.PrintCommunication = True
End Sub
Function Update(LoopCount As Integer)
getRowNumber = LoopCount
End Function
Panel.xls!Update
Sub Update()
Dim AutoUpdateTargetFile As String
Dim AutoUpdateWB As Workbook
For RowNumber = 1 To (Range("AutoUpdate.File").Rows.Count - 1)
If (Range("AutoUpdate.File").Rows(RowNumber) <> "") Then
AutoUpdateTargetFile = Range("Sys.Path") & Range("Client.Path").Rows(RowNumber) & Range("AutoUpdate.Path ").Rows(RowNumber) & Range("AutoUpdate.File").Rows(RowNumber)
Set AutoUpdateWB = Workbooks.Open(Filename:=AutoUpdateTargetFile, UpdateLinks:=3)
AutoUpdateWB.RunAutoMacros Which:=xlAutoOpen
Application.Run "Auto_Update.xls!Flat"
AutoUpdateWB.Close
End If
Next RowNumber
End Sub
1). You have declared Public var:
Public RowNumber As Integer
so remove the local declaration of the same var in Sub
Dim RowNumber As Integer 'remove
2). Regarding your second issue on 'how to pass the argument", refer to the following example demonstrating two options of passing arguments to Sub ByVal or ByRef:
Sub Example(ByVal Num1 As Integer, ByRef Num2 As Integer)
'code
End Sub
Hope this will help. Best regards,
Related
I am now trying to achieve something like the query function in Google Sheets. Obviously in this GIF, someone has already done that. I wonder how they could do that in Excel / VBA.
My specific question is: in VBA, how to fill other cells' formulas by entering a formula in a specific cell? (replicate the function used in this GIF and not using VBA + advanced filter)
Enter a formula in cell A3
Press CTRL + SHIFT + ENTER
Receive results
This is what I got so far:
The code in a standard module:
Sub run_sql_sub(sql)
On Error Resume Next
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
With cn
.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & _
This Workbook.FullName _
& ";Extended Properties=""Excel 12.0 Xml;HDR=YES;IMEX=1"";"
.Open
End With
rs.Open sql, cn
Application.ScreenUpdating = False
ActiveSheet.Range("A1:XFD1048576").ClearContents
For intColIndex = 0 To rs.Fields.Count - 1
Range("A1").Offset(0, intColIndex).Value = rs.Fields(intColIndex).Name
Next
Range("A2").CopyFromRecordset rs
Application.ScreenUpdating = True
rs.Close: cn.Close: Set rs = Nothing: Set cn = Nothing
End Sub
And this code is in activesheet's module:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim KeyCells As Range
Set KeyCells = ActiveSheet.Range("A1")
If Not Application.Intersect(KeyCells, Range(Target.Address)) _
Is Nothing Then
If InStr(KeyCells.Value2, "mi_sql") > 0 Then
sql = Right(KeyCells.Value2, Len(KeyCells.Value2) - Len("mi_sql "))
run_sql_sub sql
End If
End If
End Sub
Update 08.04.2019: found a solution
' Code in standard Module
Public collectCal As Collection
Private ccal As CallerCal
Sub subResizeKQ(caller As CallerInfo)
On Error Resume Next
Application.EnableEvents = False
If caller.Id <> "" Then
Application.Range(caller.Id).ClearContents
Application.Range(caller.Id).Resize(caller.rows, caller.cols).FormulaArray = caller.FomulaText
End If
Application.EnableEvents = True
End Sub
Function ResizeKQ(value As Variant) As Variant
If ccal Is Nothing Then Set ccal = New CallerCal
If collectCal Is Nothing Then Set collectCal = New Collection
Dim caller As New CallerInfo
Dim rows As Long, cols As Long
Dim arr As Variant
arr = value
rows = UBound(arr, 1) - LBound(arr, 1) + 1
cols = UBound(arr, 2) - LBound(arr, 2) + 1
Dim rgcaller As Range
Set rgcaller = Application.caller
caller.Id = rgcaller.Address(True, True, xlA1, True, True)
caller.rows = rgcaller.rows.Count
caller.cols = rgcaller.Columns.Count
caller.FomulaText = rgcaller.Resize(1, 1).Formula
If caller.rows <> rows Or caller.cols <> cols Then
caller.rows = rows
caller.cols = cols
collectCal.Add caller, caller.Id
End If
ResizeKQ = arr
End Function
Function fRandArray(numRow As Long, numCol As Long) As Variant
Application.Volatile True
ReDim arr(1 To numRow, 1 To numCol)
For i = 1 To numRow
For j = 1 To numCol
arr(i, j) = Rnd
Next
Next
fRandArray = ResizeKQ(arr)
End Function
'--------------------------------------------------------------------------
' code in Class Module name CallerCal
Private WithEvents AppEx As Application
Private Sub AppEx_SheetCalculate(ByVal Sh As Object)
Dim caller As CallerInfo
If collectCal Is Nothing Then Exit Sub
For Each caller In collectCal
subResizeKQ caller
collectCal.Remove caller.Id
Set caller = Nothing
Next
Set collectCal = Nothing
End Sub
Private Sub Class_Initialize()
Set AppEx = Application
End Sub
Private Sub Class_Terminate()
Set AppEx = Nothing
End Sub
'--------------------------------------------------------------------------
' code in Class Module name CallerInfo
Public rows As Long
Public cols As Long
Public Id As String
Public FomulaText As String
To test it, go to Excel Sheet, enter the following test formula in A1:
=fRandArray(10,10)
P.S: If anyone is using Excel 365 Insider Program, Microsoft has published this kind of formula called Dynamic Array Function:
https://support.office.com/en-ie/article/dynamic-arrays-and-spilled-array-behavior-205c6b06-03ba-4151-89a1-87a7eb36e531
I agree with the other comments - MS doesn't seem to provide a way to do this natively, and any way of doing it directly would probably involve some Excel-breaking memory manipulation.
However...
I suggest taking your method one step further and generalizing it
Copy and paste this class into a text file, then import it into VBA (which allows Attribute VB_PreDeclaredID = True and Attribute Item.VB_UserMemId = 0):
RangeEdit
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "RangeEdit"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Private colRanges As Collection
Private colValues As Collection
Private Sub Class_Initialize()
Set colRanges = New Collection
Set colValues = New Collection
End Sub
Public Property Let Item(rng_or_address As Variant, value As Variant)
Attribute Item.VB_UserMemId = 0
colRanges.Add rng_or_address
colValues.Add value
End Property
Public Sub flush(sh As Worksheet)
Application.EnableEvents = False
While colRanges.Count > 0
If TypeName(colRanges(1)) = "Range" Then
colRanges(1).value = colValues(1)
ElseIf TypeName(colRanges(1)) = "String" Then
sh.Range(colRanges(1)).value = colValues(1)
End If
colRanges.Remove 1
colValues.Remove 1
Wend
Application.EnableEvents = True
End Sub
Make your Workbook_SheetChange method the following:
Private Sub Workbook_SheetChange(ByVal sh As Object, ByVal Target As Range)
RangeEdit.flush sh
End Sub
Now you can create a UDF that modifies other cells. The way it works is it queues up all the modifications you make and only runs them after the cell loses focus. The syntax allows you to treat it almost like the regular Range function. You can run it either with an address string or with an actual range (though you might want to add an error if it's not either one of those).
Here is a quick example UDF that can be run from an Excel cell formula:
Public Function MyUDF()
RangeEdit("A1") = 4
RangeEdit("B1") = 6
RangeEdit("C4") = "Hello everyone!"
Dim r As Range
Set r = Range("B12")
RangeEdit(r) = "This is a test of using a range variable"
End Function
For your specific case, I would replace
For intColIndex = 0 To rs.Fields.Count - 1
Range("A1").Offset(0, intColIndex).Value = rs.Fields(intColIndex).Name
Next
with
For intColIndex = 0 To rs.Fields.Count - 1
RangeEdit(Range("A1").Offset(0, intColIndex)) = rs.Fields(intColIndex).Name
Next
And to copy the recordset I would define the following function (it assumes that the recordset cursor is set to the first record. if you Move it previously you might want to have rs.MoveFirst in there):
Public Sub FormulaSafeRecordsetCopy(rs As ADODB.Recordset, rng As Range)
Dim intColIndex As Long
Dim intRowIndex As Long
While Not rs.EOF
For intColIndex = 0 To rs.Fields.Count - 1
RangeEdit(rng.Offset(intRowIndex, intColIndex)) = rs.Fields(intColIndex).value
Next
rs.MoveNext
intRowIndex = intRowIndex + 1
Wend
End Sub
Hi I'm pretty new at the vba so please don't shoot my code :-).
I have a set of repaeting code's. I woukld like to simplify this code by using the code name with an increasing number. I can't get it to run. Can someone help me a bit on the road to get this going.
Below what I'm trying.
The second block is a part of the code now (it's 40 blocks of the same code only increasing the number)
Sub sheet41()
Dim i As Integer
Dim chkname As Integer
chkname = "SheetCheckBox" & i
i = 1
Do
i = i + 1
If chkname.Visible = False Then Exit Sub
If chkname.value = True Then
Sheets("Item_" & i).Select
Call Finalize
End If
Loop Until i = ThisWorkbook.Worksheets.Count
End Sub
This is the old code:
Sub Sheet1()
If SheetCheckBox1.Visible = False Then Exit Sub
If SheetCheckBox1.value = True Then
Sheets("Item_1").Select
Call Finalize
End If
End Sub
Sub Sheet2()
If SheetCheckBox2.Visible = False Then Exit Sub
If SheetCheckBox2.value = True Then
Sheets("Item_2").Select
Call Finalize
End If
End Sub
Sub Sheet3()
If SheetCheckBox3.Visible = False Then Exit Sub
If SheetCheckBox3.value = True Then
Sheets("Item_3").Select
Call Finalize
End If
End Sub
As you can see this should be possible to clean I asume.
This should do it. If finalize isn't called on a worksheet then the reason why is printed to the Immediate Window.
Sub ProcessWorkSheets()
Dim check As MSForms.CHECKBOX
Dim i As Integer
For i = 1 To Worksheets.Count
On Error Resume Next
Set check = Worksheets(i).OLEObjects("SheetCheckBox" & i).Object
On Error GoTo 0
If check Is Nothing Then
Debug.Print Worksheets(i).Name; " - Checkbox not found"
Else
If check.Visible And check.Value Then
Worksheets(i).Select
Call Finalize
Else
Debug.Print Worksheets(i).Name; " - Checkbox", "Visible", check.Visible, "Value:", check.Value
End If
End If
Set check = Nothing
Next
End Sub
If the checkboxes on the Sheet are ActiveX Controls, you can use this to access the checkboxes:
Sheets("sheet1").OLEObjects("chkTest").Object
if you want to change the value of a checkbox, use it like this:
Sheets("sheet1").OLEObjects("chkTest").Object.Value = True
now replace "sheet1" with your actual sheet name and change the "chkTest" to your string chkname
So your complete code should be like this:
Dim i As Integer
Dim sheetname As String
Dim chkname As String
sheetname = "YOUR SHEETNAME HERE"
For i = 1 To ThisWorkbook.Worksheets.Count Step 1
chkname = "SheetCheckBox" & i
If Sheets(sheetname).OLEObjects(chkname).Object.Visible = False Then Exit Sub
If Sheets(sheetname).OLEObjects(chkname).Object.Value = True Then
Sheets("Item_" & i).Select
Call Finalize
End If
Next i
This is a newb question:
I have two sheets. Sheet 1 is where there is a form to enter data. When you double click on any cell in column A, a user form pop up comes up. You enter a few keys from any entry that is in the A column of sheet 2 and it autocompletes.
The problem I am having is: I only want to enter data on a specific cell, for instance A1 .. not the whole column of A. A second thing I wanted was that instead of a double click, I wanted it to work with a single click. Can anyone please help.
Here is the VBA code for Sheet 1 where you enter the data
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Dim uiChosen As String
Dim MyList As Range
Dim myPrompt As String
If Target.Column <> 1 Then Exit Sub
Set MyList = Sheet2.Range("Cariler")
myPrompt = "Lütfen Bir Cari Seçin"
uiChosen = UserForm1.ChooseFromList(MyList, myPrompt, Default:=Target.Value, xlFilterStyle:=xlContains)
If StrPtr(uiChosen) <> 0 Then
Target.Value = uiChosen
Cancel = True
End If
End Sub
Here is the code for the user form:
Option Explicit
' in userform's code module
Dim FullList As Variant
Dim FilterStyle As XlContainsOperator
Dim DisableMyEvents As Boolean
Dim AbortOne As Boolean
Const xlNoFilter As Long = xlNone
Private Sub butCancel_Click()
Unload Me
End Sub
Private Sub butOK_Click()
Me.Tag = "OK"
Me.Hide
End Sub
Private Sub ComboBox1_Change()
Dim oneItem As Variant
Dim FilteredItems() As String
Dim NotFlag As Boolean
Dim Pointer As Long, i As Long
If DisableMyEvents Then Exit Sub
If AbortOne Then AbortOne = False: Exit Sub
If TypeName(FullList) Like "*()" Then
ReDim FilteredItems(1 To UBound(FullList))
DisableMyEvents = True
Pointer = 0
With Me.ComboBox1
Select Case FilterStyle
Case xlBeginsWith: .Tag = LCase(.Text) & "*"
Case xlContains: .Tag = "*" & LCase(.Text) & "*"
Case xlDoesNotContain: .Tag = "*" & LCase(.Text) & "*": NotFlag = True
Case xlEndsWith: .Tag = "*" & LCase(.Text)
Case xlNoFilter: .Tag = "*"
End Select
For Each oneItem In FullList
If (LCase(oneItem) Like .Tag) Xor NotFlag Then
Pointer = Pointer + 1
FilteredItems(Pointer) = oneItem
End If
Next oneItem
.List = FilteredItems
.DropDown
DisableMyEvents = False
If Pointer = 1 Then .ListIndex = 0
End With
End If
End Sub
Private Sub ComboBox1_Click()
butOK.SetFocus
End Sub
Private Sub ComboBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Select Case KeyCode
Case vbKeyReturn: Call butOK_Click
Case vbKeyUp, vbKeyDown: AbortOne = True
End Select
End Sub
Private Sub Label1_Click()
End Sub
Private Sub UserForm_Activate()
ComboBox1.SetFocus
If ComboBox1.Text <> vbNullString Then
Call ComboBox1_Change
End If
End Sub
Private Sub UserForm_Initialize()
ComboBox1.MatchEntry = fmMatchEntryNone
End Sub
Public Function ChooseFromList(ListSource As Variant, Optional Prompt As String = "Choose one item", _
Optional Title As String = "Cari Arama Programı", Optional Default As String, _
Optional xlFilterStyle As XlContainsOperator = xlBeginsWith) As String
Dim Pointer As Long, oneItem As Variant
If TypeName(ListSource) = "Range" Then
With ListSource
Set ListSource = Application.Intersect(.Cells, .Parent.UsedRange)
End With
If ListSource Is Nothing Then Exit Function
If ListSource.Cells.Count = 1 Then
ReDim FullList(1 To 1): FullList(1) = ListSource.Value
ElseIf ListSource.Rows.Count = 1 Then
FullList = Application.Transpose(Application.Transpose(ListSource))
Else
FullList = Application.Transpose(ListSource)
End If
ElseIf TypeName(ListSource) Like "*()" Then
ReDim FullList(1 To 1)
For Each oneItem In ListSource
Pointer = Pointer + 1
If UBound(FullList) < Pointer Then ReDim Preserve FullList(1 To 2 * Pointer)
FullList(Pointer) = oneItem
Next oneItem
ReDim Preserve FullList(1 To Pointer)
ElseIf Not IsObject(ListSource) Then
ReDim FullList(1 To 1)
FullList(1) = CStr(ListSource)
Else
Err.Raise 1004
End If
Me.Caption = Title
Label1.Caption = Prompt
FilterStyle = xlFilterStyle
DisableMyEvents = True
ComboBox1.Text = Default
ComboBox1.List = FullList
DisableMyEvents = False
butOK.SetFocus
Me.Show
With UserForm1
If .Tag = "OK" Then ChooseFromList = .ComboBox1.Text
End With
End Function
There is no single click event. Use Intersect to test wherther or not the target cell is within a given range.
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Not Intersect(Target, Range("A1")) Is Nothing Then
Dim uiChosen As String
Dim MyList As Range
Dim myPrompt As String
If Target.Column <> 1 Then Exit Sub
Set MyList = Sheet2.Range("Cariler")
myPrompt = "Lütfen Bir Cari Seçin"
uiChosen = UserForm1.ChooseFromList(MyList, myPrompt, Default:=Target.Value, xlFilterStyle:=xlContains)
If StrPtr(uiChosen) <> 0 Then
Target.Value = uiChosen
Cancel = True
End If
End If
End Sub
This is blowing my mind. I can't find what I'm doing wrong. I hope it's just a case of tunnel vision.
I get error message "Object variable or With block variable not set- 1"
Option Explicit:
Public mWB As Workbook
Public Sub runCSSBatch()
On Error GoTo Errorcatch
1 mWB = ActiveWorkbook
Call createTempSheet
Call findworksheet
Errorcatch:
MsgBox Err.Description & "-" & Erl
Application.DisplayAlerts = False
mWB.Sheets("TEMP").Delete
Application.DisplayAlerts = True
End Sub
Instead of ActiveWorkbook, it may be, ThisWorkbook
set mwb=thisworkbook
I eventually found many things wrong with my script.
I did end up using Set in front of ActiveWorkbook (using ThisWorkbook
was not necessary)
I believe the comment about using 1: instead of 1 to catch the error
was valid.
I am now running the script with quite a few less subs than I was
before.
I also had made the mistake of using Cells() inside Range() when one
excludes the other
I tried to pass a Worksheet Variable to a Sub (apparently you can't
do that).
I'm sure there was more but I can't recall.
I'm going to chalk it up to having a shitty day. :/
As you can see the below code looks nothing like what I had posted initially.
Option Explicit:
Public mWB As Workbook
Public Sub runCSSBatch()
Set mWB = ActiveWorkbook
mWB.Sheets.Add.Name = "TEMP"
Dim WSh As Worksheet
For Each WSh In mWB.Worksheets
If InStr(WSh.Name, "CSS") = 1 Then
Call parseRowText(WSh.Name)
End If
Next
End Sub
Private Sub parseRowText(WSName As String)
Dim rowCount As Long
Dim I As Long
Dim columnCount As Long
Dim B As Long
Dim dataString As String
Dim WS As Worksheet
Set WS = mWB.Worksheets(WSName)
columnCount = mWB.Sheets(WSName).UsedRange.Columns.Count
rowCount = mWB.Sheets(WSName).UsedRange.Rows.Count
For I = 2 To rowCount
For B = 1 To columnCount
dataString = ""
If mWB.Sheets(WSName).Cells(1, B).Value = "STOP" Then
dataString = "}"
Call addToTempSheet(dataString)
Exit For
Else
If B = 1 Then
dataString = mWB.Sheets(WSName).Cells(I, B).Value & "{"
Call addToTempSheet(dataString)
Else
If dataString & mWB.Sheets(WSName).Cells(I, B).Value = "" Then
Else
dataString = mWB.Sheets(WSName).Cells(1, B).Value & ":"
dataString = dataString & mWB.Sheets(WSName).Cells(I, B).Value & ";"
Call addToTempSheet(dataString)
End If
End If
End If
Next B
Next I
End Sub
Private Sub addToTempSheet(dString As String)
mWB.Sheets("TEMP").Range("A" & Rows.Count).End(xlUp).Offset(1).Value = dString
End Sub
My app below checks a workbook which has a list of items sold for a particular month identified with a serial number. There is also a comment column next to the item.
Each month when I run the app it tells me if the same item was sold and the comments next to the item.
"Item found in sheet labeled august 2014"
"Comments for that item"
if I run the app again on the workbook when it gets an additional sheet added, it's going to add the "items found..." Again.
I have the results starting from column 20 and beyond, I only need to delete the duplicates in those columns.
Option Explicit On
Option Infer Off
Imports System.Net.Mail
Imports System.IO
Imports Microsoft.Office.Interop
Imports Microsoft.Office.Interop.Excel
Imports System.Runtime.InteropServices
Imports Excel = Microsoft.Office.Interop.Excel
Imports System.Text.RegularExpressions
Public Class Form1
Dim fileName As String = ""
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Function ColumnIndexToColumnLetter(colIndex As Integer) As String
Dim div As Integer = colIndex
Dim colLetter As String = String.Empty
Dim modnum As Integer = 0
While div > 0
modnum = (div - 1) Mod 26
colLetter = Chr(65 + modnum) & colLetter
div = CInt((div - modnum) \ 26)
End While
Return colLetter
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Button1.Enabled = False
Button1.Text = "Patience"
Button1.Refresh()
System.Windows.Forms.Application.DoEvents()
Dim app As New Excel.Application
app.Visible = False
Dim wbBase As Excel.Workbook = app.Workbooks.Open(TextBox1.Text)
' * create style *
'
Dim xlStyles As Excel.Styles = wbBase.Styles
Dim xlStyle As Excel.Style = Nothing
Dim isstyleexists As Boolean = False
'
' * check if this style exist *
'
For Each xlStyle In xlStyles
If xlStyle.Name = "NewStyle" Then
isstyleexists = True
Exit For
End If
Next
'
' * if this does not exist so add new one *
' ' get Range "A1"
If (Not isstyleexists) Then
xlStyles.Add("NewStyle")
xlStyle = xlStyles.Item("NewStyle")
End If
Dim snName As String
Dim snName2 As String
Dim cmt2 As String
For Each basesheet As Excel.Worksheet In wbBase.Sheets
Dim iiii As Integer = basesheet.Cells(1, basesheet.Columns.Count).End(Excel.XlDirection.xlToLeft).Column + 1
Dim iii As Integer = basesheet.Cells(1, basesheet.Columns.Count).End(Excel.XlDirection.xlToLeft).Column + 1
Dim iv As Integer = iii + 1
For i As Integer = 1 To 20
If Not basesheet.Cells(1, i).Value Is Nothing AndAlso basesheet.Cells(1, i).Value.Contains("Serial Number") Then
snName = ColumnIndexToColumnLetter(i)
Exit For
End If
Next
If Not snName Is Nothing Then
For Each checksheet As Excel.Worksheet In wbBase.Sheets
If basesheet.Name <> checksheet.Name Then
For i As Integer = 1 To 20
If Not checksheet.Cells(1, i).Value Is Nothing AndAlso checksheet.Cells(1, i).Value.Contains("Serial Number") Then
snName2 = ColumnIndexToColumnLetter(i)
Exit For
End If
Next
For i As Integer = 1 To 20
If Not checksheet.Cells(1, i).Value Is Nothing AndAlso checksheet.Cells(1, i).Value.Contains("Comments") Then
cmt2 = ColumnIndexToColumnLetter(i)
Exit For
End If
Next
If Not snName2 Is Nothing Then
Dim baseobj As Object = basesheet.Range(snName & "2:" & snName & basesheet.Range(snName & basesheet.Rows.Count).End(Excel.XlDirection.xlUp).Row).Value
Dim checkobj As Object = checksheet.Range(snName2 & "2:" & snName2 & checksheet.Range(snName2 & checksheet.Rows.Count).End(Excel.XlDirection.xlUp).Row).Value
Dim cmtobj As Object = checksheet.Range(cmt2 & "2:" & cmt2 & checksheet.Range(snName2 & checksheet.Rows.Count).End(Excel.XlDirection.xlUp).Row).Value
Dim basetmp(DirectCast(baseobj, Object(,)).Length, 1) As Object
Dim v As Integer = 0
Dim bool As Boolean = False
For i As Integer = 1 To DirectCast(baseobj, Object(,)).Length
For ii As Integer = 1 To DirectCast(checkobj, Object(,)).Length
If Not baseobj(i, 1) Is Nothing AndAlso Not checkobj(ii, 1) Is Nothing AndAlso Trim(baseobj(i, 1).ToString) = Trim(checkobj(ii, 1).ToString) Then
bool = True
basetmp(i, 0) = "Serial # Exists in " & checksheet.Name
basetmp(i, 1) = cmtobj(ii, 1)
End If
Next
v += 1
Next
If bool Then
basesheet.Range(basesheet.Cells(1, iii), basesheet.Cells(v, iv)).Style = "NewStyle"
basesheet.Range(basesheet.Cells(1, iii), basesheet.Cells(v, iv)).Borders.Weight = Excel.XlBorderWeight.xlThin
basesheet.Range(basesheet.Cells(1, iii), basesheet.Cells(v, iv)).Borders.LineStyle = Excel.XlLineStyle.xlContinuous
basesheet.Range(basesheet.Cells(1, iii), basesheet.Cells(v, iv)).Value = basetmp
basesheet.Cells(1, iii).value = "Results Found"
basesheet.Cells(1, iii).Font.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red)
basesheet.Cells(1, iii).HorizontalAlignment = Excel.Constants.xlCenter
basesheet.Cells(1, iii).Font.Bold = True
basesheet.Columns.AutoFit()
iii += 2
iv += 2
End If
End If
End If
Next
End If
Next
wbBase.Save()
wbBase.Close()
app.Quit()
MessageBox.Show("Done", "Three in Thirty", MessageBoxButtons.OK)
Button1.Text = "Start"
Button1.Enabled = True
End Sub
It looks like you are reprocessing the previously processed sheets each month.
It might be easier to avoid reprocessing old sheets, than to avoid duplicating entries from reprocessing old sheets.
Instead of using nested loops of worksheets, I would probably try a pattern like:
* find basesheet
* find latest checksheet
* process the checksheet for items sold
If users might accidentally add things to old sheets, then I would consider locking old sheets when you do the processing to help ensure data integrity.