I am trying to merge 4 models into one. All models have a common part of the code as well as a model specific parts. I have created a user form, which identifies what model to run based on the criteria selected by user. So the user form has 4 criteria and produces 12 different outcomes. So I want to create a sub which will run the commons parts of the code for all outcomes and then outcome specific parts.
Currently the user form code displays message boxes depending on the selection. I want to connect this code (see it below) to the code in the VBA model and use in the IF structure. For example, if a user select Template 1, Private data type and Tier 2, No Wipe Out then the model will run the common part, then the parts for Template 1 with Private data type, Tier 2 and No Wipe Out and then again a common part.
For example, the Wipe Out/No Wipe Out part is similar for all models. Other parts have a lot of similarities.
Here is the User Form code:
Private Sub modelrun_btn_Click()
If radiotempl1.Value = True Then
If datatype.Value = "Public" Then
If wipe_format.Value = True Then
MsgBox "Template 1 Public Model Wipe Out"
Else
MsgBox "Template 1 Public Model No Wipe Out"
End If
ElseIf datatype.Value = "Private" Then
If radiotier1.Value = True Then
If wipe_format.Value = True Then
MsgBox "Template 1 Private Model Tier 1 Wipe Out"
Else
MsgBox "Template 1 Private Model Tier 1 No Wipe Out"
End If
Else
If wipe_format.Value = True Then
MsgBox "Template 1 Private Model Tier 2 Wipe Out"
Else
MsgBox "Template 1 Private Model Tier 2 No Wipe Out"
End If
End If
Else
MsgBox "Please select a data type"
End If
ElseIf radiotempl2.Value = True Then
If datatype.Value = "Public" Then
If wipe_format.Value = True Then
MsgBox "Template 2 Public Model Wipe Out"
Else
MsgBox "Template 2 Public Model No Wipe Out"
End If
ElseIf datatype.Value = "Private" Then
If radiotier1.Value = True Then
If wipe_format.Value = True Then
MsgBox "Template 2 Private Model Tier 1 Wipe Out"
Else
MsgBox "Template 2 Private Model Tier 1 No Wipe Out"
End If
ElseIf radiotier2.Value = True Then
If wipe_format.Value = True Then
MsgBox "Template 2 Private Model Tier 2 Wipe Out"
Else
MsgBox "Template 2 Private Model Tier 2 No Wipe Out"
End If
Else
MsgBox "Please select a tier"
End If
Else
MsgBox "Please select a data type"
End If
Else
MsgBox "Please select a template"
End If
End Sub
And this is an example of one of the models. Basically it opens an Excel file generated by a different programme, copies one or two worksheets into the model (depending on template), there are worksheets in teh model with commented out formulas, so the macro uncomments them, hides those which are not needed and does some formatting.
Sub UploadData()
Dim FileOpenDial As Variant
Dim FileSaveAs As Variant
Dim wb As Workbook
Dim activeWB As Workbook
Dim bFileSaveAs As Boolean
Dim finstart As Range
Dim endcell As Range, startcell As Range
Dim yearsno As Range
Dim numrowsadj As Integer
Dim cfyearsno As Range
Dim numrows As Integer
Dim numrowscf As Integer
Dim c As Range
Dim decimaltab As Range
Dim d As Range
Dim MySheets As Variant
Dim r As Range
'Import the data
'Optimize Code
Application.ScreenUpdating = False
EventState = Application.EnableEvents
Application.EnableEvents = False
CalcState = Application.Calculation
Application.Calculation = xlCalculationManual
PageBreakState = ActiveSheet.DisplayPageBreaks
ActiveSheet.DisplayPageBreaks = False
Application.DisplayAlerts = False
Set activeWB = Application.ActiveWorkbook
FileOpenDial = Application.GetOpenFilename(FileFilter:="Excel Files (*.XML), *.XML", Title:="Select File To Be Opened")
If FileOpenDial = False Then Exit Sub
Set wb = Workbooks.Open(FileOpenDial)
Sheets(Array("Accounts", "Types")).Select
Sheets(Array("Accounts", "Types")).Copy Before:=activeWB.Sheets(1)
wb.Close savechanges:=False 'or True
'Save a file
FileSaveAs = Application.GetSaveAsFilename(FileFilter:="Exel Files (*.xlsx), *.xlsx", Title:="Select Name To Save The File")
If FileSaveAs <> False Then
ActiveWorkbook.SaveAs Filename:=FileSaveAs, _
FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
End If
'Unhide sheets
For Each MySheets In Array("FS", "CF", "tables", "Calcs", "tables_for_output", "Tier_I", "Tier_II")
Worksheets(MySheets).Visible = True
Next
'Build tables from the data
Sheets("FS").Select
'Remove apostrophe from the formulas
For Each c In Range("D1:D250").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
'FillRight Formulas
Set yearsno = ThisWorkbook.Sheets("Accounts").Range("F2:Z2")
numrows = Application.WorksheetFunction.CountA(yearsno)
If 5 - numrows >= 0 Then
numrowsadj = 0
Else: numrowsadj = 5 - numrows
End If
With ThisWorkbook.Sheets("FS")
Set startcell = .Range("D1")
Set endcell = Cells(Range("D" & Rows.Count).End(xlUp).Row, 3 + numrows + numrowsadj)
Set finstart = .Range(startcell.Address & ":" & endcell.Address)
finstart.FillRight
End With
ThisWorkbook.Sheets("FS").Range("C1").Select
'Build CF
Sheets("CF").Select
'Remove apostrophe from the formulas
For Each c In Range("F1:F160").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
'FillRight Formulas
Set cfyearsno = ThisWorkbook.Sheets("FS").Range("C1:XFD1")
numrowscf = Application.WorksheetFunction.CountA(cfyearsno)
With ThisWorkbook.Sheets("CF")
Set startcell = .Range("F1")
If numrowscf = 3 Then
Set endcell = Range("F" & Rows.Count).End(xlUp).Offset(, 1)
Set finstart = .Range(startcell.Address & ":" & endcell.Address)
finstart.FillRight
ElseIf numrowscf > 3 Then
Set endcell = Range("F" & Rows.Count).End(xlUp).Offset(, 2)
Set finstart = .Range(startcell.Address & ":" & endcell.Address)
finstart.FillRight
Else
End If
End With
ThisWorkbook.Sheets("CF").Range("E1").Select
'Activite the Summary tables
Sheets("tables").Select
For Each c In Range("C1:G88").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
Sheets("tables").Range("B1").Select
'Activate Calcs
Sheets("Calcs").Select
'Remove apostrophe from the formulas
For Each c In Range("B1:H22").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
'Activate tables_for_output
Sheets("tables_for_output").Select
For Each c In Range("B2:O43").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
'Activate Tier_I
Sheets("Tier_I").Select
For Each c In Range("D6:I15").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
'Activate Tier_II
Sheets("Tier_II").Select
For Each c In Range("D6:I15").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
'Hide the working worksheets
Sheets(Array("Model", "Calcs")).Visible = False
'Stop Optimize Code
'Call OptimizeCode_End
'ActiveSheet.DisplayPageBreaks = True
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
'Replace Conditional formating with normal based on a checkbox
If Sheets("Model").Shapes("Check Box 7").ControlFormat.Value = 1 Then
Sheets("tables_for_output").Select
Range("F4:O4").Select
For Each r In Selection
r.Interior.Color = r.DisplayFormat.Interior.Color
Next r
Selection.FormatConditions.Delete
'Tier_I
Sheets("Tier_I").Select
Range("F6:H15").Select
For Each r In Selection
r.Interior.Color = r.DisplayFormat.Interior.Color
Next r
Selection.FormatConditions.Delete
Sheets("Tier_I").Range("C2").Select
'Tier_II
Sheets("Tier_II").Select
Range("F6:H15").Select
For Each r In Selection
r.Interior.Color = r.DisplayFormat.Interior.Color
Next r
Selection.FormatConditions.Delete
End If
ThisWorkbook.Sheets("tables_for_output").Select
Sheets("tables_for_output").Range("A1").Select
ThisWorkbook.Sheets("Tier_II").Select
Sheets("Tier_II").Range("C2").Select
'Hide a Tier sheet based on the selection
If Sheets("Calcs").Range("B24").Value = 1 Then
Sheets("Tier_II").Visible = False
ElseIf Sheets("Calcs").Range("B24").Value = 2 Then
Sheets("Tier_I").Visible = False
End If
'Formatting
'Columns Width
ThisWorkbook.Sheets("FS").Cells.SpecialCells(xlCellTypeVisible).EntireColumn.AutoFit
ThisWorkbook.Sheets("CF").Cells.SpecialCells(xlCellTypeVisible).EntireColumn.AutoFit
'Decimal Formatting
'tables
Sheets("tables").Select
Set decimaltab = [C2:E16,C25:E49,C62:E69,C71:E75,C77:E83]
For Each d In decimaltab.SpecialCells(xlCellTypeFormulas, xlNumbers)
If Abs(d.Value) < 20 And Round(d.Value, 0) <> 0 Then
d.NumberFormat = "0.0;(0.0)"
Else
d.NumberFormat = "#,##0;(#,##0)"
End If
Next d
'tables_for_output
Sheets("tables_for_output").Select
Set decimaltab = [B2:B3,B11:D15,B17:D18,B20:D23,B33:D34,B37:D39,B43:D43]
For Each d In decimaltab.SpecialCells(xlCellTypeFormulas, xlNumbers)
If Abs(d.Value) < 101 And Round(d.Value, 0) <> 0 Then
d.NumberFormat = "0.0;(0.0)"
Else
d.NumberFormat = "#,##0;(#,##0)"
End If
Next d
Application.ScreenUpdating = True
ActiveWorkbook.Save
End Sub
I just cannot figure out a good way to integrate the user form into the existing code. I guess I need to get the output of the user form in a form of variable and them to build an algorithm. But I do not know how to start.
Basically I need to achieve the following algorithm:
Fill User Form
If any of the options are not selected ask user to do it
Run Upload Data sub
Optimise
Open external Excel file
If Template 1 Selected Then
Import Accounts and Types sheets
Else
Import Accounts sheet
End If
Save file under a different name
Unhide hiden templates
If Template 1 Then
If datatype Private Then
Unhide FS_1, CF_1, tables, calcs, tables_for_output, Tier 1, Tier 2
Rename FS_1 and CF_1 to FS and CF
Else
Unhide FS_1, CF_1, tables
Rename FS_1 and CF_1 to FS and CF
Else
If datatype Private Then
Unhide FS_2, CF_2, tables, calcs, tables_for_output, Tier 1, Tier 2
Rename FS_2 and CF_2 to FS and CF
Else
Unhide FS_2, CF_2
Rename FS_2 and CF_2 to FS and CF
End If
End If
Activite Templates
Activate FS
Activate CF
Activate tables
If datatype Private
Activate calcs
Acivate tables_for_output
Activate Tier 1
Activate Tier 2
Otimisation ends
Tidying up
Hide unneeded sheets
If datatype Private Then
If Tier 1 Then
Hide Model, cacls, Tier 2
Else
Hide Model, calcs, Tier 1
Else
Hide Model
End If
If datatype Private replace conditional formatting with normal
If Tier 1
In tables_for_otput, Tier 1
Else
in tables_for_output, Tier 2
End If
Additional Formattng
If datatype Public
Format FS, CF, tables
Else
Format FS, CF, table, tables for output
End If
Workbook Save
Sub End
I've worked on it last weekend but got interrupted rather early on. Apologies for the delay.
The ByVal wasn't really needed here, I may have worded myself incorrectly. Here's the documentation in case you'd like to read up on it: Byval & ByRef
As for the code, I tried to get it done the way you mentioned but wipe_out was not included in your Sub? So couldn't implement it either.
Hope the code works and was the way you specified:
Option Explicit
Sub UploadData()
Dim FileOpenDial As Variant
Dim FileSaveAs As Variant
Dim wb As Workbook, activeWB As Workbook
Dim bFileSaveAs As Boolean
Dim finstart As Range, endcell As Range, startcell As Range
Dim yearsno As Range, cfyearsno As Range
Dim numrows As Long, numrowscf As Long, numrowsadj As Long 'I prefer to not have number rows in Integer due to limitations of size
Dim c As Range, d As Range, r As Range, decimaltab As Range
Dim MySheets As String, tier As String
Dim templ As Integer, dType As Integer, wipe As Integer
'Checking user form
If radiotempl1.Value Then templ = 1
ElseIf radiotempl2.Value Then templ = 2
Else
MsgBox "Please select a template"
End If
If dataType.Value = "Public" Then
dType = 1
ElseIf dataType.Value = "Private" Then
dType = 2
Else
MsgBox "Please select a data type"
End If
If wipe_format.Value Then wipe = 1
If radiotier1.Value Then tier = "Tier_1"
If radiotier2.Value Then tier = "Tier_2"
Else
If dType = 2 Then
MsgBox "Please select a tier"
Exit Sub
End If
End If
If templ + dType < 2 Then Exit Sub
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
ActiveSheet.DisplayPageBreaks = False
Application.DisplayAlerts = False
Set activeWB = Application.ActiveWorkbook
FileOpenDial = Application.GetOpenFilename(FileFilter:="Excel Files (*.XML), *.XML", Title:="Select File To Be Opened")
If FileOpenDial = False Then Exit Sub
Set wb = Workbooks.Open(FileOpenDial)
'you mentioned "copies one or two worksheets into the model (depending on the template) but I'm not sure which way you wanted this
Sheets(Array("Accounts", "Types")).Copy Before:=activeWB.Sheets(1) 'avoid select as much as possible
wb.Close savechanges:=False 'or True
'Save a file
FileSaveAs = Application.GetSaveAsFilename(FileFilter:="Exel Files (*.xlsx), *.xlsx", Title:="Select Name To Save The File")
If FileSaveAs <> False Then
ActiveWorkbook.SaveAs Filename:=FileSaveAs, _
FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
End If
copySheet "FS", templ 'this is to copy the right sheet and delete the FS if it alreasdy existed from a previous time you ran the code
copySheet "CF", templ
Set yearsno = ThisWorkbook.Sheets("Accounts").Range("F2:Z2")
With Sheets("FS")
'Remove apostrophe from the formulas
For Each c In .Range("D1:D250").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
numrows = Application.WorksheetFunction.CountA(yearsno)
If 5 - numrows >= 0 Then
numrowsadj = 0
Else: numrowsadj = 5 - numrows
End If
Set startcell = .Range("D1")
Set endcell = Cells(Range("D" & Rows.Count).End(xlUp).Row, 3 + numrows + numrowsadj)
Set finstart = .Range(startcell.Address & ":" & endcell.Address)
finstart.FillRight
Set cfyearsno = .Range("C1:XFD1")
numrowscf = Application.WorksheetFunction.CountA(cfyearsno)
End With
With Sheets("CF")
'Remove apostrophe from the formulas
For Each c In Range("F1:F160").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
Set startcell = .Range("F1")
If numrowscf = 3 Then
Set endcell = Range("F" & Rows.Count).End(xlUp).Offset(, 1)
Set finstart = .Range(startcell.Address & ":" & endcell.Address)
finstart.FillRight
ElseIf numrowscf > 3 Then
Set endcell = Range("F" & Rows.Count).End(xlUp).Offset(, 2)
Set finstart = .Range(startcell.Address & ":" & endcell.Address)
finstart.FillRight
Else
End If
End With
With Sheets("tables")
For Each c In .Range("C1:G88").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
End With
With Sheets("Calcs")
For Each c In Range("B1:H22").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
End With
With Sheets("tables_for_output")
For Each c In Range("B2:O43").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
End With
'no need to hide sheets if you keep them hidden :)
Calculate
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
With Sheets("tables_for_output")
For Each r In Range("F4:O4")
r.Interior.Color = r.DisplayFormat.Interior.Color
Next r
Range("F4:O4").FormatConditions.Delete
End With
If dType = 2 Then
With Sheets(tier) 'same here as last time with tier
For Each c In .Range("D6:I15").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
For Each r In Range("F6:H15")
r.Interior.Color = r.DisplayFormat.Interior.Color
Next r
Range("F6:H15").FormatConditions.Delete
.Visible = True
End With
End With
'Formatting
'Columns Width
ThisWorkbook.Sheets("FS").Cells.SpecialCells(xlCellTypeVisible).EntireColumn.AutoFit
ThisWorkbook.Sheets("CF").Cells.SpecialCells(xlCellTypeVisible).EntireColumn.AutoFit
'Decimal Formatting
'tables
With Sheets("tables")
Set decimaltab = Union(.Range("C2:E16"), .Range("C25:E49"), .Range("C62:E69"), .Range("C71:E75"), .Range("C77:E83"))
For Each d In decimaltab.SpecialCells(xlCellTypeFormulas, xlNumbers)
If Abs(d.Value) < 20 And Round(d.Value, 0) <> 0 Then
d.NumberFormat = "0.0;(0.0)"
Else
d.NumberFormat = "#,##0;(#,##0)"
End If
Next d
'tables_for_output
With Sheets("tables_for_output")
Set decimaltab = Union(.Range("B2:B3"), .Range("B11:D15"), .Range("B17:D18"), .Range("B20:D23"), .Range("B33:D34"), .Range("B37:D39"), .Range("B43:D43"))
For Each d In decimaltab.SpecialCells(xlCellTypeFormulas, xlNumbers)
If Abs(d.Value) < 101 And Round(d.Value, 0) <> 0 Then
d.NumberFormat = "0.0;(0.0)"
Else
d.NumberFormat = "#,##0;(#,##0)"
End If
Next d
.Activate
'You will have to decide which sheet you actually want to be presented first but I got rid of the copious use of .Select
'For now it's this one
End With
Application.ScreenUpdating = True
ActiveWorkbook.Save
End Sub
Sub copySheet(shtName As String, templNo As Integer)
If WorksheetExists(shtName) Then ActiveWorkbook.Sheets(shtName).Delete
shtName = shtName & "_" & templNo
Sheets(shtName).Copy After:=Worksheets(Worksheets.Count)
With ActiveSheet
.Name = Left(shtName, 2)
.Visible = True
End With
End Sub
Function WorksheetExists(shtName As String, Optional wb As Workbook) As Boolean
Dim sht As Worksheet
If wb Is Nothing Then Set wb = ActiveWorkbook
On Error Resume Next
Set sht = wb.Sheets(shtName)
On Error GoTo 0
WorksheetExists = Not sht Is Nothing
End Function
If you have any more questions, feel free to ask
I am working on a sort of "BOT" for Outlook (using Outlook VBA), in which I receive info by mail, split the mail body, paste it on Excel and execute Excel macros.
After adding the part where I call the Excel macro, I get
'1004 - application-defined or object-defined error'
if I'm running this for the second + time.
xlApp.Application.Run "AINT.Cali_B_Click"
Even though I'm setting my Excel variables to nothing and using .close and .quit, Excel is still running.
How can I end the application reference that is keeping Excel open?
Here's my full code:
Private Sub inboxItems_ItemAdd(ByVal Item As Object)
On Error GoTo ErrorHandler
Dim Msg As Outlook.MailItem
Dim MessageInfo
Dim Result
Dim splitter() As String
Dim splitter2() As String
Dim loopH As String
Dim str As Variant
Dim LoopCali As Integer
Dim i, j As Integer
Dim xlApp As Object
Dim sourceWB As Object
Dim Header, QuoteSTG, AINT, Treinamento As Object
Dim strFile, file_name As String
Dim shellcom As String
i = 1
If TypeName(Item) = "MailItem" Then
If InStr(Item.Subject, "BOT") > 0 Then
splitter = Split(Item.Body, vbCrLf)
Set xlApp = CreateObject("Excel.Application")
strFile = "C:\Users\e1257539\Desktop\SMOBOT\SMO_TOOL_BOT.xlsm"
With xlApp
.Visible = False
.EnableEvents = False
.DisplayAlerts = False
End With
Set sourceWB = Workbooks.Open(strFile)
sourceWB.Activate
Set Header = sourceWB.Sheets(4)
Set QuoteSTG = sourceWB.Sheets(13)
Set AINT = sourceWB.Sheets(7)
Set Treinamento = sourceWB.Sheets(10)
file_name = QuoteSTG.Range("A" + CStr(QuoteSTG.Range("B1").Value2)).Value2
QuoteSTG.Range("A" + CStr(QuoteSTG.Range("B1").Value2)).Value2 = ""
If splitter(2) = "Calibração" Then
loopH = splitter(26)
LoopCali = CInt(loopH)
sourceWB.Save
Header.Range("D6").Value2 = splitter(22)
Header.Range("D8").Value2 = splitter(12)
Header.Range("F4").Value2 = "AINT"
Header.Range("F3").Value2 = "EXW"
Header.Range("C2").Value2 = file_name
Header.Range("C4").Value2 = "Calibração"
Header.Range("L2").Value2 = "30"
Header.Range("K12").Value2 = Item.Subject '< criar string?
j = 40
For i = 1 To LoopCali
splitter2 = Split(splitter(j), "-")
AINT.Range("N7").Value2 = splitter2(0)
AINT.Range("N13").Value2 = splitter2(1)
j = j + 2
If splitter(j) <> "" Then
AINT.Range("N14").Value2 = splitter(j)
End If
j = j + 2
If splitter(j) <> "" Then
AINT.Range("N16").Value2 = splitter(j)
End If
j = j + 2
If splitter(j) <> "" Then
If splitter2(0) <> "RMT" Then
AINT.Range("N15").Value2 = splitter(j)
End If
End If
j = j + 2
If splitter(j) <> "" Then
AINT.Range("N17").Value2 = splitter(j)
End If
j = j + 2
xlApp.Application.Run "AINT.Cali_B_Click" '< calling the excel sub
Next i
End If
End If
End If
'Closing excel
MkDir "C:\Users\e1257539\Desktop\SMOBOT\" + file_name
sourceWB.SaveAs FileName:="C:\Users\e1257539\Desktop\SMOBOT\" + file_name + "\" + file_name
sourceWB.Close (False)
xlApp.Quit
Set xlApp = Nothing
Set sourceWB = Nothing
Set AINT = Nothing
Set QuoteSTG = Nothing
Set Header = Nothing
ErrorHandler:
MsgBox Err.Number & " - " & Err.Description
If Not sourceWB Is Nothing Then
sourceWB.Close (False)
End If
If Not xlApp Is Nothing Then
xlApp.Quit
End If
Set xlApp = Nothing
Set sourceWB = Nothing
Set AINT = Nothing
Set QuoteSTG = Nothing
Set Header = Nothing
End Sub
Turns out using xlApp.Application.Run "AINT.Cali_B_Click" or xlApp.Application.Run sourceWB.Name & "AINT.Cali_B_Click" left open references on the VBA code.
The way to call the code without lefting any open is using CallByName,
As in Call CallByName(AINT, "Cali_B_Click", VbMethod)
This way the VBA code can call the function and run as many times as needed without the current error.
I get this error:
subscript out of range.
I do not have the debug option, only OK and HELP.
One time on 20 the macro works. The rest of time I'm getting this error.
The code makes you choose the path you want to search and next the text you want to find in the workbook in the path chosen. It searches in sub folders too. After that it sends back the file name, sheet name, which cell and what text is in the cell.
The macro runs but pops that error after searching 4 to 5 different files.
Dim AppObject As New Class1
Public WS As Worksheet
Sub SearchWKBooksSubFolders(Optional Folderpath As Variant, Optional Str As Variant)
Dim myfolder As String
Dim a As Single
Dim sht As Worksheet
Dim Lrow As Single
Dim Folders() As String
Dim Folder As Variant
ReDim Folders(0)
Dim wbk As Workbook
If IsMissing(Folderpath) Then
Set WS = Sheets.Add
With Application.FileDialog(msoFileDialogFolderPicker)
.Show
myfolder = .SelectedItems(1) & "\"
End With
Str = Application.InputBox(prompt:="Nom de la Personne:", Title:="Personne a chercher", Type:=2)
If Str = "" Then Exit Sub
WS.Range("A1") = "Semaine"
WS.Range("B1") = "Journée"
WS.Range("C1") = "Cellule"
WS.Range("D1") = "Nom"
Folderpath = myfolder
Value = Dir(myfolder, &H1F)
Else
If Right(Folderpath, 2) = "\\" Then
Exit Sub
End If
Value = Dir(Folderpath, &H1F)
End If
Do Until Value = ""
If Value = "." Or Value = ".." Then
Else
If GetAttr(Folderpath & Value) = 16 Then
Folders(UBound(Folders)) = Value
ReDim Preserve Folders(UBound(Folders) + 1)
ElseIf Right(Value, 3) = "xls" Or Right(Value, 4) = "xlsx" Or Right(Value, 4) = "xlsm" Then
On Error Resume Next
Workbooks.Open Filename:=Folderpath & Value, Password:="zzzzzzzzzzzz"
If Err.Number <> 0 Then
WS.Range("A4").Offset(a, 0).Value = Value
WS.Range("B4").Offset(a, 0).Value = "Password protected"
a = a + 1
On Error GoTo 0
Else
For Each sht In ActiveWorkbook.Worksheets
'Expand all groups in sheet
sht.Outline.ShowLevels RowLevels:=8, ColumnLevels:=8
Set c = sht.Cells.Find(Str)
If Not c Is Nothing Then
firstAddress = c.Address
Do
Lrow = WS.Range("A" & Rows.Count).End(xlUp).Row
WS.Range("A1").Offset(Lrow, 0).Value = Value
WS.Range("B1").Offset(Lrow, 0).Value = sht.Name
WS.Range("C1").Offset(Lrow, 0).Value = c.Address
WS.Range("D1").Offset(Lrow, 0).Value = c.Value
Set c = sht.Cells.FindNext(c)
Loop While Not c Is Nothing And c.Address <> firstAddress
End If
Next sht
End If
Workbooks(Value).Close False
On Error GoTo 0
End If
End If
Value = Dir
Loop
For Each Folder In Folders
SearchWKBooksSubFolders (Folderpath & Folder & "\")
Next Folder
Cells.EntireColumn.AutoFit
End Sub
you can debug on your own without the debugger of the IDE.
Simply put On Error Resume Next/On Error Goto 0 very close to each other in order to restrict the statements which can raise errors. ie the second On Error Goto 0 is too far.
I can debug more effectively simply putting between statements something like that:
a = a + 1
debug.print "I am here"
b = b -5
debug.print "I am there"
c = 5 / 0
debug.print "You can't see me"
So you can find when the error is raised
I wrote this Access/VBA program. It works but only when I am not running other applications or few users are in the database. I need some ideas on streamlining the code. So it is not so system intensive. The program basically allows a user to pick a folder and then combines all worksheets in that folder in one excel document. My current idea is just to tell users to close all excel files when trying to run the program. Please Help:
Sub Excel_open()
Dim myXL As Excel.Application
Dim myXLS As Excel.Workbook
Const errExcelNotRunning = 429
On Error GoTo HandleIt
Set myXL = GetObject(, "Excel.application")
myXL.Visible = True
Set myXLS = myXL.Workbooks.Add
Call CombineWorkbooks(myXL)
HandleIt:
If Err.Number = errExcelNotRunning Then
Set myXL = CreateObject("Excel.Application")
Err.Clear
Resume Next
End If
End Sub
Sub CombineWorkbooks(myXL)
'Macro that combines the files into one folder
myXL.AskToUpdateLinks = False
myXL.DisplayAlerts = False
Dim CurFile As String, dirloc As String, strNamesheet As String
Dim DestWB As Workbook
Dim ws As Object ' allows for diffrent sheet types
'Add select the director function
dirloc = GetFolderName & "\" 'location of files not working want to select the file only
CurFile = Dir(dirloc & "*.xls*")
myXL.ScreenUpdating = False
myXL.EnableEvents = False
Set DestWB = Workbooks.Add(xlWorksheet)
Do While CurFile <> vbNullString
Dim OrigWB As Workbook
Set OrigWB = Workbooks.Open(FileName:=dirloc & CurFile, ReadOnly:=True)
'need to change a name active name is not doing it
CurFile = Left(CurFile, 4) ' This is no longer 29
'CurFile = Left(Left(CurFile, Len(CurFile) - 5), 29)
For Each ws In OrigWB.Sheets
ws.Copy After:=DestWB.Sheets(DestWB.Sheets.Count)
' Use the name to give the sheet a name
strNamesheet = Left((ws.Name), 25) & ";"
If OrigWB.Sheets.Count > 1 Then
DestWB.Sheets(DestWB.Sheets.Count).Name = strNamesheet & CurFile ' & ws.Index
Else
DestWB.Sheets(DestWB.Sheets.Count).Name = CurFile
End If
Next
OrigWB.Close SaveChanges:=False
CurFile = Dir
Loop
myXL.DisplayAlerts = False
DestWB.Sheets(1).Delete
myXL.DisplayAlerts = True
myXL.ScreenUpdating = True
myXL.EnableEvents = True
Set DestWB = Nothing
Call Delete_empty_Sheets(myXL)
Call Sort_Active_Book
MsgBox "Done"
'Call Xcombine_the_Matching
End Sub
Sub Delete_empty_Sheets(myXL)
'goes through all sheets and deletes
Reset_the_search:
For Each wsElement In Worksheets
If wsElement.Range("A2") = "" And wsElement.Range("B2") = "" Then
myXL.DisplayAlerts = False
wsElement.Delete
GoTo Reset_the_search
myXL.DisplayAlerts = True
End If
Next wsElement
End Sub
Sub Xcombine_the_Matching()
'I think I can make the order work
'change and transpose the array
Dim varStart As Variant
Dim wsCompare As Worksheet
Dim strMatch As String
'Dim varCompare As Variant
Dim strVareince As String
Dim strCurrentName As String
'you need to build a loop to solve this problem
For Each wsCompare In Worksheets
strVareince = Add_Array(Application.Transpose(wsCompare.Range("A1:Z1")))
For Each wsNompare In Worksheets
If wsNompare.Name <> strCurrentName Then
If strVareince = Add_Array(Application.Transpose(wsNompare.Range("A1:Z1"))) Then
MsgBox ("Matched with worksheet " & wsNompare.Name)
End If
End If
Next
Next
End Sub
Function array_to_string(x) As String
For Z = 1 To 26
array_to_string = array_to_string & x(Z, 1) & ";"
Next Z
End Function
Function GetFolderName(Optional OpenAt As String) As String
'Allows you to select the folder director that you want to combine
Dim lCount As Long
GetFolderName = vbNullString
With Application.FileDialog(msoFileDialogFolderPicker)
.InitialFileName = OpenAt
.Show
For lCount = 1 To .SelectedItems.Count
GetFolderName = .SelectedItems(lCount)
Next lCount
End With
End Function
Function Add_Array(x) As String
'turns an excel document
For d = 1 To UBound(x)
Add_Array = Add_Array & x(d, 1)
Next d
End Function
Sub Read_data()
'this the
End Sub
Sub Sort_Active_Book()
Dim i As Integer
Dim j As Integer
Dim iAnswer As VbMsgBoxResult
'
' Prompt the user as which direction they wish to
' sort the worksheets.
'
iAnswer = MsgBox("Sort Sheets in Ascending Order?" & Chr(10) _
& "Clicking No will sort in Descending Order", _
vbYesNoCancel + vbQuestion + vbDefaultButton1, "Sort Worksheets")
For i = 1 To Sheets.Count
For j = 1 To Sheets.Count - 1
'
' If the answer is Yes, then sort in ascending order.
'
If iAnswer = vbYes Then
If UCase$(Sheets(j).Name) > UCase$(Sheets(j + 1).Name) Then
Sheets(j).Move After:=Sheets(j + 1)
End If
'
' If the answer is No, then sort in descending order.
'
ElseIf iAnswer = vbNo Then
If UCase$(Sheets(j).Name) < UCase$(Sheets(j + 1).Name) Then
Sheets(j).Move After:=Sheets(j + 1)
End If
End If
Next j
Next i
End Sub
You are passing your Excel Application object into your subroutines, but not using it fully, neither are you explicitly referencing the libraries:
Sub CombineWorkbooks(myXL)
Dim DestWB As Excel.Workbook ' <<<
Set DestWB = myXL.Workbooks.Add(xlWorksheet) ' <<<
End Sub
Run through your code and fix all of these first, then test & supply more feedback on what the precise symptoms of the problems are.
I've tried something similar to this:
Set kitap = CreateObject("Excel.Application")
If IsXlsOpen() = True Then
kitap.Application.Quit
End If
.. but didnt work out so I neeed to find how to close all excel files before starting my program in vb6
EDIT: Full code here:
Dim i As Integer
Dim kitap As Object
Dim strcnn As String
Dim cnn As New ADODB.Connection
Dim Cmd As New ADODB.Command
Dim rs As New ADODB.Recordset
Private Sub Form_Load()
strcnn = "myconn"
cnn.Open strcnn
Cmd.ActiveConnection = cnn
End Sub
Public Function dotdate(ByRef elem) As String
Dim day, month, year As String
year = Right(elem, 4)
month = Mid(elem, Len(elem) - 5, 2)
day = Mid(elem, 1, Len(elem) - 6)
If Len(day) = 1 Then
day = "0" & day
End If
dotdate = day & "." & month & "." & year
End Function
Public Function IsXlsOpen(wbName) As String
Dim xl As Excel.Application
IsXlsOpen = False
On Error Resume Next
Set xl = GetObject(, "Excel.Application")
If Err.Number <> 0 Then Exit Function
xl.Workbooks(wbName).Activate
If Err.Number = 0 Then IsXlsOpen= True
End Function
Private Sub Command1_Click()
Dim i As Integer
Dim cek As String
Set kitap = CreateObject("Excel.Application")
If IsXlsOpen("my.xls") = True Then
kitap.Application.Quit
End If
kitap.Workbooks.Add
cek = "Select * From blabla"
rs.Open cek, cnn
If rs.EOF = True Then
Situation.Caption = "Situation : EOF"
Else
kitap.Cells(i + 1, 1).Value = "ID"
kitap.Cells(i + 1, 2).Value = "Caption"
kitap.Cells(i + 1, 3).Value = "Date"
i = i + 1
Do While Not rs.EOF
kitap.Cells(i + 1, 1).Value = rs.Fields("id")
kitap.Cells(i + 1, 2).Value = rs.Fields("capt")
kitap.Cells(i + 1, 3).Value = dotdate(rs.Fields("date"))
rs.MoveNext
i = i + 1
Loop
rs.Close
End If
kitap.ActiveWorkbook.SaveAs (App.Path & "\my.xls")
kitap.Application.Quit
Situation.Caption = "Situation : Excel Formatted Report Ready."
Exit Sub
err:
rs.Close
Situation.Caption = "Critical Error! : Connection error detected. Please reset action."
End Sub
While I'm more a vbscript and vba guy, a bit more info would help:
ie what is IsXlsOpen?
what is your full kitmap code, ie have you opened and closed workbooks?
do you have any other xl instances open (before or during your code)?.
this link often solves VBA issues, in fixing global references
Note that it is good practice to close/quit workbooks/instances and set them to Nothing, ie in Tushar's code
xlWB.Close False
xlApp.Quit
Set xlWB = Nothing
Set xlApp = Nothing
To save and close all workbooks, read more
Option Explicit
Sub CloseAndSaveOpenWorkbooks()
Dim Wkb As Workbook
With Application
.ScreenUpdating = False
' Loop through the workbooks collection
For Each Wkb In Workbooks
With Wkb
' if the book is read-only
' don't save but close
If Not Wkb.ReadOnly Then
.Save
End If
' We save this workbook, but we don't close it
' because we will quit Excel at the end,
' Closing here leaves the app running, but no books
If .Name <> ThisWorkbook.Name Then
.Close
End If
End With
Next Wkb
.ScreenUpdating = True
.Quit 'Quit Excel
End With
End Sub