How to use a Variable in different a Userform/module

bcmk29

Board Regular
Joined
Oct 20, 2022
Messages
55
Office Version
  1. 365
Platform
  1. Windows
  2. MacOS
I've got 2 different UserForms (UserForm & DataMap) with multiple modules in them.

1. Here's the code of my first Form UserForm. Where I'm allowing the user to select a spreadsheet and assign the file name to Importworkbook.

VBA Code:
Private Sub UserForm_Initialize()
'DataMap.Show vbModeless

    Dim LR, IB As Long
    Dim FileLocation As String
   
    Sheets("Input").Select
    Range("A1").Select
    Sheets("Sheet3").Range("R1").Value = 0
    file = ActiveWorkbook.Name
    LR = Cells(Rows.Count, 1).End(xlUp).Row
   
    If LR = 1 Then Else GoTo ok
   
        [B]FileLocation = Application.GetOpenFilename("(*.xlsx),")
       
        If FileLocation = "False" Then
            MsgBox "No file selected to import.", 48
            Unload Me
        Exit Sub
        End If
    End If
   
    Set Importworkbook = Workbooks.Open(Filename:=FileLocation)[/B]
   
    If Importworkbook.Sheets.Count > 1 Then
reIB:
        IB = Application.InputBox("Enter worksheet number", "Worksheet selection", , , , , , 1)
            If IB > Sheets.Count Then
                MsgBox "Invalid Sheet Input, Try Again.", 48, "Entry Required"
                GoTo reIB
            Else
                Sheets(IB).Select
            End If
            GoTo hi
    Else: End If
hi:
    ActiveSheet.Range("A1").Select
    Range(Selection, Selection.End(xlToRight)).Copy
    Workbooks(file).Activate
    Sheets("Sheet3").Select
    Range("P2").Select
        Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
        :=False, Transpose:=True
    Application.CutCopyMode = False
    Range("P1").Select
ok:
End Sub

2. Here's the code for my second Form DataMap, where I'm replicating the same set of codes from above. Instead, I just need to get the name of Importworkbook from my earlier code which is assigned in different userform/module. Please assist.

VBA Code:
Sub DataImport()
    Dim LR As Long
    Dim FileLocation As String
    Dim A, A1 As Integer
    LR = Cells(Rows.Count, 1).End(xlUp).Row
    If LR = 1 Then Else GoTo ok

[B]    FileLocation = Application.GetOpenFilename("(*.xlsx),")
    If FileLocation = "False" Then
        MsgBox "No file selected to import.", 48
        Exit Sub
    End If
    Set Importworkbook = Workbooks.Open(Filename:=FileLocation)[/B]

    ThisWorkbook.Worksheets(2).Activate
    SH = ThisWorkbook.Worksheets(4).Cells(Rows.Count, 19).End(xlUp).Row
For A = 2 To SH

'MsgBox DataMap!mastrImportworkbook
    Importworkbook.Worksheets(1).Range(Sheets("Sheet3").Range("T" & A).Value).Copy ThisWorkbook.Worksheets(2).Cells(1, A - 1)
Next A
    Application.ScreenUpdating = True
    ThisWorkbook.Worksheets(3).Range("A1:u1").Copy
    ThisWorkbook.Worksheets(2).Range("A1:u1").Select
    Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
        :=False, Transpose:=False
    Selection.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, SkipBlanks _
        :=False, Transpose:=False
    Application.CutCopyMode = False
    Range("A1").Select
    Importworkbook.Close
    Application.ScreenUpdating = True

    ThisWorkbook.Worksheets(4).Select
    Range("P2").Select
    Range(Selection, Selection.End(xlDown)).Select
    Selection.ClearContents
    Range("S2").Select
    Range(Selection, Selection.End(xlDown)).Select
    Selection.ClearContents
    Range("R1").Select
    Selection.ClearContents
    ThisWorkbook.Worksheets(2).Select
    Range("A1").Select
ok:
   UserForm1.Show
End Sub
 
Hi bmck29,

thanks for sharing more information on the file. A lot of trouble is created by my use of error handling in the code, I will be working on it. I now hopefully have a better understanding of what should go where. Give me some time, I think it's better to test thoroughly than coming up with non-working code again.

Ciao,
Holger
 
Upvote 0

Excel Facts

Last used cell?
Press Ctrl+End to move to what Excel thinks is the last used cell.
Hi bcmk29,

starting with sad news first: I'm sorry I could not spot what you intended to do after reading the opening post. I misinterpreted some codes which let to action on the wrong worksheets. I hope I have done better now.

I changed the CodeNames for the worksheets as well as the Name for some:

TabName OldTabName NewCodename
BlindsidedResulttblResult
InputInputtblInput
QueryQuerytblQuery
Sheet3Sheet3tblAdmin


I changed the destination sheet in DataImport from Input to Result as on the start of the UserForm a check on the number of entries in Column A on Sheet Input is made - if we let the data at that place we would need to clear it.

A new module was inserted in ThisWorkbook/DieseArbeitsmappe:

VBA Code:
Private Sub Workbook_Open()
  Application.Goto tblInput.Range("G4"), False
End Sub

Please mind that I reverted the code to work with the CodeNames of the worksheets.

All the code for the UserForm in one go:

VBA Code:
Private Sub UserForm_Initialize()
  Dim lngIndexWS      As Long       'index of worksheet in new workbook if more than one worksheet
  Dim lngWS           As Long       'counter for index of worksheets in opened workbook
  Dim varFile         As Variant    'variable to hold path and filename for workbook to open
  Dim varArr          As Variant    'values for the header values to be copied
  Dim strWS           As String     'Holding the names of worksheets of new workbook
  Dim ws              As Worksheet  'for looping worksheets in new workbook
  Dim wb              As Workbook   'for looping through all open workbooks
  Dim blnRunOnce      As Boolean    'boolean for getting information about worksheets,
  Dim blnUnload       As Boolean    'boolean whether to unload the UF
  
  Const cstrProcName  As String = "UserForm1_Initialize"
  Const cblnBcmk      As Boolean = True
  
  On Error GoTo err_here
  blnUnload = False
  
  If tblInput.Cells(Rows.Count, 1).End(xlUp).Row <> 1 Then GoTo end_here
  
  If gwkbImport Is Nothing Then
    varFile = Application.GetOpenFilename("(*.xlsx),", MultiSelect:=False)
    If varFile = False Then
      MsgBox "No file selected to import.", 48
      blnUnload = True
      GoTo end_here
    End If
    Set gwkbImport = Workbooks.Open(Filename:=varFile)
  Else
    For Each wb In Workbooks
      If wb.Name = gwkbImport.Name Then Exit For
    Next wb
    Set gwkbImport = Workbooks.Open(Filename:=varFile)
  End If
  
  
  If cblnBcmk Then MsgBox gwkbImport.FullName
  If gwsNewHeader Is Nothing Then
    If gwkbImport.Worksheets.Count > 1 Then
      blnRunOnce = False
reIB:
      If blnRunOnce = False Then
        For Each ws In gwkbImport.Worksheets
          lngWS = lngWS + 1
          strWS = strWS & lngWS & " : " & ws.Name & vbCrLf
        Next ws
        blnRunOnce = True
      End If
      lngIndexWS = Application.InputBox("Enter worksheet number" & vbCrLf & Left(strWS, Len(strWS) - 1), "Worksheet selection", , , , , , 1)
      If lngIndexWS > gwkbImport.Worksheets.Count Then
        MsgBox "Invalid Worksheet Input, Try Again.", 48, "Entry Required"
        GoTo reIB
      ElseIf lngIndexWS = 0 Then
        MsgBox "Procedure cancelled", vbInformation, "Stopping here"
        gwkbImport.Close False
        Set gwkbImport = Nothing
        blnUnload = True
        GoTo end_here
      Else
        Set gwsNewHeader = gwkbImport.Worksheets(lngIndexWS)
      End If
    Else
      Set gwsNewHeader = gwkbImport.Worksheets(1)
    End If
  End If

  Err.Clear
  On Error GoTo 0
  If blnUnload = False Then
    tblAdmin.Range("P2:P" & tblAdmin.Rows.Count).ClearContents
    varArr = gwsNewHeader.Range("A1").Resize(1, gwsNewHeader.Cells(1, Columns.Count).End(xlToLeft).Column)
    varArr = WorksheetFunction.Transpose(varArr)
    tblAdmin.Range("P2").Resize(UBound(varArr), 1).Value = varArr
    Application.Goto tblAdmin.Range("P1"), True
  End If

end_here:
  Err.Clear
  On Error GoTo 0
  If blnUnload Then End
  Exit Sub

err_here:
  Debug.Print "Actual procedure name: " & cstrProcName & vbCrLf & _
              "Error number: " & Err.Number & vbCrLf & _
              "Error description: " & Err.Description
  Err.Clear
  On Error GoTo 0
  Resume end_here

End Sub

Private Sub UserForm_Activate()
  Dim rng2List        As Range          'object holding range for List for CBs
  Dim objCtrl         As Control        'object to cycle through the Controls on the UF
  
  Set rng2List = tblAdmin.Range("P2", tblAdmin.Cells(Rows.Count, 16).End(xlUp))
  
  For Each objCtrl In Me.Controls
    If TypeOf objCtrl Is MSForms.ComboBox Then
      objCtrl.List = rng2List.Value
    End If
  Next objCtrl
  
  Application.Goto tblInput.Range("A1"), True
  
  Set rng2List = Nothing
  
End Sub

Private Sub cmdAdd_Click()
  Dim objNewLB        As Object
  Dim objNewCB        As Object
  Dim lngUFHeight     As Long
  Dim lngLR_P         As Long
  Dim lngLR_U         As Long
  
  Static slngAddCtrls As Long                     'number of controls added
  
  Const cblnHaHoBe    As Boolean = True           '!!!!! change to False, uncomment and adjust your code to suit
                                                  'my UserForm has other dimensions than yours, I called my Buttons
                                                  'cmdAdd and cmdProc
  
  lngLR_P = tblAdmin.Cells(tblAdmin.Rows.Count, 16).End(xlUp).Row
  lngLR_U = tblAdmin.Cells(tblAdmin.Rows.Count, 21).End(xlUp).Row

  If cblnHaHoBe Then
    'all dimensions are tailored for my sample
    slngAddCtrls = slngAddCtrls + 1
    'general height of UserForm
    Me.Height = Me.Height + (30 * slngAddCtrls)
    'start of last constant element, new ones should be listed below
    lngUFHeight = 230
    Set objNewLB = Me.Controls.Add("Forms.listbox.1", True)
    With objNewLB
      .Name = "Listbox" & slngAddCtrls
      .Left = 30
      .Height = 22
      .Width = 108
      .Top = lngUFHeight + (25 * slngAddCtrls)
      .RowSource = tblAdmin.Name & "!U10:U" & lngLR_U
    End With
    Set objNewCB = Me.Controls.Add("Forms.combobox.1", True)
    With objNewCB
      .Name = "Combobox" & slngAddCtrls
      .Left = 168
      .Height = 22
      .Width = 108
      .Top = lngUFHeight + (25 * slngAddCtrls)
      .RowSource = tblAdmin.Name & "!P2:P" & lngLR_P
    End With
    With cmdAdd
      .Left = 30
      .Top = lngUFHeight + 5 + (25 * (slngAddCtrls + 2))
    End With
    With cmdProc
      .Left = 168
      .Top = lngUFHeight + 5 + (25 * (slngAddCtrls + 2))
    End With
    With Label9
      .Left = 30
      .Top = lngUFHeight + (30 * (slngAddCtrls + 1))
      If slngAddCtrls > 0 Then
        .Caption = slngAddCtrls & " Fields Added"
      End If
    End With
  Else
'    slngAddCtrls = slngAddCtrls + 1
'    lngUFHeight = 202
'    Set objNewLB = Me.Controls.Add("Forms.listbox.1", True)
'    slngAddCtrls = slngAddCtrls + 1
'    With objNewLB
'        .Name = "Listbox" & slngAddCtrls
'        .Left = 17
'        .lngUFHeight = 20
'        .Width = 92
'        .Top = lngUFHeight + (25 * slngAddCtrls)
'        .RowSource = "Sheet3!U10:U" & lngLR_U
'    End With
'    Set objNewCB = Me.Controls.Add("Forms.combobox.1", True)
'    lngUFHeight = 200
'    With objNewCB
'        .Name = "Combobox" & slngAddCtrls
'        .Left = 114
'        .Width = 107
'        .Top = lngUFHeight + (25 * slngAddCtrls)
'        .RowSource = "Sheet3!P2:P" & lngLR_P
'    End With
'    lngUFHeight = 225
'    With CommandButton1
'        .Left = 30
'        .Top = lngUFHeight + (25 * slngAddCtrls)
'    End With
'    lngUFHeight = 225
'    With CommandButton2
'        .Left = 126
'        .Top = lngUFHeight + (25 * slngAddCtrls)
'    End With
'    lngUFHeight = 305
'    DataMap.lngUFHeight = lngUFHeight + (25 * slngAddCtrls)
'    lngUFHeight = 260
'    With Label9
'        .Caption = slngAddCtrls & " Field Added"
'        .Left = 86
'        .Top = lngUFHeight + (25 * slngAddCtrls)
'        If slngAddCtrls > 1 Then
'            .Caption = slngAddCtrls & " Fields Added"
'        End If
'    End With
'    Me.Tag = slngAddCtrls
  End If

End Sub

Private Sub cmdProc_Click()
  Dim lngCounter        As Long
  Dim blnComplete       As Boolean
  Dim objCtrl           As Control
  Dim objColNoDupes     As New Collection
  
  For Each objCtrl In Me.Controls
    If TypeOf objCtrl Is MSForms.ComboBox Then
      With objCtrl
        blnComplete = Len(.Value) > 0
        If blnComplete Then
          On Error Resume Next
          objColNoDupes.Add .Value, CStr(.Value)
          If Err.Number = 457 Then
            MsgBox "Item '" & .Value & "' has already been chosen, please alter and try again.", vbInformation, "Double encountered"
            .SetFocus
            GoTo end_here
          End If
        Else
          MsgBox "Please fill blank field", 48, "Entry Required"
          .SetFocus
          GoTo end_here
        End If
      End With
    End If
    Err.Clear
    On Error GoTo 0
  Next objCtrl
  
  If blnComplete Then
    Err.Clear
    On Error GoTo 0
    With tblAdmin
      .Range("S2", .Range("S" & .Rows.Count).End(xlUp)).ClearContents
      For lngCounter = 1 To objColNoDupes.Count
        .Range("S" & lngCounter + 1).Value = objColNoDupes(lngCounter)
      Next lngCounter
    End With
    Unload Me
    Call DataImport
  End If

end_here:
  Err.Clear
  On Error GoTo 0

End Sub

Code for module modDataImport:

VBA Code:
Sub DataImport()
  Dim lngImport     As Long
  Dim lngItems      As Long
  Dim strCol        As String

  If Not gwsNewHeader Is Nothing Then
    Application.ScreenUpdating = False
    tblResult.UsedRange.ClearContents
    tblQuery.Range("A1:U1").Copy
    With tblResult.Range("A1:U1")
        .PasteSpecial Paste:=xlPasteValues, _
                      Operation:=xlNone, _
                      SkipBlanks:=False, _
                      Transpose:=False
        .PasteSpecial Paste:=xlPasteFormats, _
                      Operation:=xlNone, _
                      SkipBlanks:=False, _
                      Transpose:=False
    End With
    Application.CutCopyMode = False
    
    With tblAdmin
      For lngImport = 2 To .Cells(Rows.Count, 19).End(xlUp).Row
        With .Range("T" & lngImport)
          If InStr(1, .Value, ":") > 0 Then
            strCol = Left(.Value, InStr(1, .Value, ":") - 1)
          Else
            strCol = .Value
          End If
        End With
        lngItems = gwsNewHeader.Range(strCol & Rows.Count).End(xlUp).Row
        gwsNewHeader.Range(strCol & 1).Resize(lngItems, 1).Copy tblResult.Cells(1, lngImport - 1)
      Next lngImport
    End With
 
    gwkbImport.Close SaveChanges:=False
    Application.ScreenUpdating = True
  
    With tblAdmin
      .Range("P2", .Cells(.Rows.Count, "P").End(xlUp)).ClearContents
      .Range("S2", .Cells(.Rows.Count, "S").End(xlUp)).ClearContents
      .Range("R1").ClearContents
    End With
  End If
  Application.Goto ThisWorkbook.Worksheets("Input").Range("A1"), Scroll:=True
   
  Set gwsNewHeader = Nothing
  Set gwkbImport = Nothing
 
End Sub

Code for module modStartUF:

VBA Code:
Public gwkbImport As Workbook
Public gwsNewHeader As Worksheet
'

Sub Call_UF()

  UserForm1.Show

End Sub

Please find the altered workbook MrE_1612814 1220041 Upload 221025

I had several runs with the sample file you supplied but no error was raised. Now I'm waiting to see what will happen on your side.

Ciao,
Holger
 
Upvote 0
Hi bcmk29,

starting with sad news first: I'm sorry I could not spot what you intended to do after reading the opening post. I misinterpreted some codes which let to action on the wrong worksheets. I hope I have done better now.

I changed the CodeNames for the worksheets as well as the Name for some:

TabName OldTabName NewCodename
BlindsidedResulttblResult
InputInputtblInput
QueryQuerytblQuery
Sheet3Sheet3tblAdmin


I changed the destination sheet in DataImport from Input to Result as on the start of the UserForm a check on the number of entries in Column A on Sheet Input is made - if we let the data at that place we would need to clear it.

A new module was inserted in ThisWorkbook/DieseArbeitsmappe:

VBA Code:
Private Sub Workbook_Open()
  Application.Goto tblInput.Range("G4"), False
End Sub

Please mind that I reverted the code to work with the CodeNames of the worksheets.

All the code for the UserForm in one go:

VBA Code:
Private Sub UserForm_Initialize()
  Dim lngIndexWS      As Long       'index of worksheet in new workbook if more than one worksheet
  Dim lngWS           As Long       'counter for index of worksheets in opened workbook
  Dim varFile         As Variant    'variable to hold path and filename for workbook to open
  Dim varArr          As Variant    'values for the header values to be copied
  Dim strWS           As String     'Holding the names of worksheets of new workbook
  Dim ws              As Worksheet  'for looping worksheets in new workbook
  Dim wb              As Workbook   'for looping through all open workbooks
  Dim blnRunOnce      As Boolean    'boolean for getting information about worksheets,
  Dim blnUnload       As Boolean    'boolean whether to unload the UF
 
  Const cstrProcName  As String = "UserForm1_Initialize"
  Const cblnBcmk      As Boolean = True
 
  On Error GoTo err_here
  blnUnload = False
 
  If tblInput.Cells(Rows.Count, 1).End(xlUp).Row <> 1 Then GoTo end_here
 
  If gwkbImport Is Nothing Then
    varFile = Application.GetOpenFilename("(*.xlsx),", MultiSelect:=False)
    If varFile = False Then
      MsgBox "No file selected to import.", 48
      blnUnload = True
      GoTo end_here
    End If
    Set gwkbImport = Workbooks.Open(Filename:=varFile)
  Else
    For Each wb In Workbooks
      If wb.Name = gwkbImport.Name Then Exit For
    Next wb
    Set gwkbImport = Workbooks.Open(Filename:=varFile)
  End If
 
 
  If cblnBcmk Then MsgBox gwkbImport.FullName
  If gwsNewHeader Is Nothing Then
    If gwkbImport.Worksheets.Count > 1 Then
      blnRunOnce = False
reIB:
      If blnRunOnce = False Then
        For Each ws In gwkbImport.Worksheets
          lngWS = lngWS + 1
          strWS = strWS & lngWS & " : " & ws.Name & vbCrLf
        Next ws
        blnRunOnce = True
      End If
      lngIndexWS = Application.InputBox("Enter worksheet number" & vbCrLf & Left(strWS, Len(strWS) - 1), "Worksheet selection", , , , , , 1)
      If lngIndexWS > gwkbImport.Worksheets.Count Then
        MsgBox "Invalid Worksheet Input, Try Again.", 48, "Entry Required"
        GoTo reIB
      ElseIf lngIndexWS = 0 Then
        MsgBox "Procedure cancelled", vbInformation, "Stopping here"
        gwkbImport.Close False
        Set gwkbImport = Nothing
        blnUnload = True
        GoTo end_here
      Else
        Set gwsNewHeader = gwkbImport.Worksheets(lngIndexWS)
      End If
    Else
      Set gwsNewHeader = gwkbImport.Worksheets(1)
    End If
  End If

  Err.Clear
  On Error GoTo 0
  If blnUnload = False Then
    tblAdmin.Range("P2:P" & tblAdmin.Rows.Count).ClearContents
    varArr = gwsNewHeader.Range("A1").Resize(1, gwsNewHeader.Cells(1, Columns.Count).End(xlToLeft).Column)
    varArr = WorksheetFunction.Transpose(varArr)
    tblAdmin.Range("P2").Resize(UBound(varArr), 1).Value = varArr
    Application.Goto tblAdmin.Range("P1"), True
  End If

end_here:
  Err.Clear
  On Error GoTo 0
  If blnUnload Then End
  Exit Sub

err_here:
  Debug.Print "Actual procedure name: " & cstrProcName & vbCrLf & _
              "Error number: " & Err.Number & vbCrLf & _
              "Error description: " & Err.Description
  Err.Clear
  On Error GoTo 0
  Resume end_here

End Sub

Private Sub UserForm_Activate()
  Dim rng2List        As Range          'object holding range for List for CBs
  Dim objCtrl         As Control        'object to cycle through the Controls on the UF
 
  Set rng2List = tblAdmin.Range("P2", tblAdmin.Cells(Rows.Count, 16).End(xlUp))
 
  For Each objCtrl In Me.Controls
    If TypeOf objCtrl Is MSForms.ComboBox Then
      objCtrl.List = rng2List.Value
    End If
  Next objCtrl
 
  Application.Goto tblInput.Range("A1"), True
 
  Set rng2List = Nothing
 
End Sub

Private Sub cmdAdd_Click()
  Dim objNewLB        As Object
  Dim objNewCB        As Object
  Dim lngUFHeight     As Long
  Dim lngLR_P         As Long
  Dim lngLR_U         As Long
 
  Static slngAddCtrls As Long                     'number of controls added
 
  Const cblnHaHoBe    As Boolean = True           '!!!!! change to False, uncomment and adjust your code to suit
                                                  'my UserForm has other dimensions than yours, I called my Buttons
                                                  'cmdAdd and cmdProc
 
  lngLR_P = tblAdmin.Cells(tblAdmin.Rows.Count, 16).End(xlUp).Row
  lngLR_U = tblAdmin.Cells(tblAdmin.Rows.Count, 21).End(xlUp).Row

  If cblnHaHoBe Then
    'all dimensions are tailored for my sample
    slngAddCtrls = slngAddCtrls + 1
    'general height of UserForm
    Me.Height = Me.Height + (30 * slngAddCtrls)
    'start of last constant element, new ones should be listed below
    lngUFHeight = 230
    Set objNewLB = Me.Controls.Add("Forms.listbox.1", True)
    With objNewLB
      .Name = "Listbox" & slngAddCtrls
      .Left = 30
      .Height = 22
      .Width = 108
      .Top = lngUFHeight + (25 * slngAddCtrls)
      .RowSource = tblAdmin.Name & "!U10:U" & lngLR_U
    End With
    Set objNewCB = Me.Controls.Add("Forms.combobox.1", True)
    With objNewCB
      .Name = "Combobox" & slngAddCtrls
      .Left = 168
      .Height = 22
      .Width = 108
      .Top = lngUFHeight + (25 * slngAddCtrls)
      .RowSource = tblAdmin.Name & "!P2:P" & lngLR_P
    End With
    With cmdAdd
      .Left = 30
      .Top = lngUFHeight + 5 + (25 * (slngAddCtrls + 2))
    End With
    With cmdProc
      .Left = 168
      .Top = lngUFHeight + 5 + (25 * (slngAddCtrls + 2))
    End With
    With Label9
      .Left = 30
      .Top = lngUFHeight + (30 * (slngAddCtrls + 1))
      If slngAddCtrls > 0 Then
        .Caption = slngAddCtrls & " Fields Added"
      End If
    End With
  Else
'    slngAddCtrls = slngAddCtrls + 1
'    lngUFHeight = 202
'    Set objNewLB = Me.Controls.Add("Forms.listbox.1", True)
'    slngAddCtrls = slngAddCtrls + 1
'    With objNewLB
'        .Name = "Listbox" & slngAddCtrls
'        .Left = 17
'        .lngUFHeight = 20
'        .Width = 92
'        .Top = lngUFHeight + (25 * slngAddCtrls)
'        .RowSource = "Sheet3!U10:U" & lngLR_U
'    End With
'    Set objNewCB = Me.Controls.Add("Forms.combobox.1", True)
'    lngUFHeight = 200
'    With objNewCB
'        .Name = "Combobox" & slngAddCtrls
'        .Left = 114
'        .Width = 107
'        .Top = lngUFHeight + (25 * slngAddCtrls)
'        .RowSource = "Sheet3!P2:P" & lngLR_P
'    End With
'    lngUFHeight = 225
'    With CommandButton1
'        .Left = 30
'        .Top = lngUFHeight + (25 * slngAddCtrls)
'    End With
'    lngUFHeight = 225
'    With CommandButton2
'        .Left = 126
'        .Top = lngUFHeight + (25 * slngAddCtrls)
'    End With
'    lngUFHeight = 305
'    DataMap.lngUFHeight = lngUFHeight + (25 * slngAddCtrls)
'    lngUFHeight = 260
'    With Label9
'        .Caption = slngAddCtrls & " Field Added"
'        .Left = 86
'        .Top = lngUFHeight + (25 * slngAddCtrls)
'        If slngAddCtrls > 1 Then
'            .Caption = slngAddCtrls & " Fields Added"
'        End If
'    End With
'    Me.Tag = slngAddCtrls
  End If

End Sub

Private Sub cmdProc_Click()
  Dim lngCounter        As Long
  Dim blnComplete       As Boolean
  Dim objCtrl           As Control
  Dim objColNoDupes     As New Collection
 
  For Each objCtrl In Me.Controls
    If TypeOf objCtrl Is MSForms.ComboBox Then
      With objCtrl
        blnComplete = Len(.Value) > 0
        If blnComplete Then
          On Error Resume Next
          objColNoDupes.Add .Value, CStr(.Value)
          If Err.Number = 457 Then
            MsgBox "Item '" & .Value & "' has already been chosen, please alter and try again.", vbInformation, "Double encountered"
            .SetFocus
            GoTo end_here
          End If
        Else
          MsgBox "Please fill blank field", 48, "Entry Required"
          .SetFocus
          GoTo end_here
        End If
      End With
    End If
    Err.Clear
    On Error GoTo 0
  Next objCtrl
 
  If blnComplete Then
    Err.Clear
    On Error GoTo 0
    With tblAdmin
      .Range("S2", .Range("S" & .Rows.Count).End(xlUp)).ClearContents
      For lngCounter = 1 To objColNoDupes.Count
        .Range("S" & lngCounter + 1).Value = objColNoDupes(lngCounter)
      Next lngCounter
    End With
    Unload Me
    Call DataImport
  End If

end_here:
  Err.Clear
  On Error GoTo 0

End Sub

Code for module modDataImport:

VBA Code:
Sub DataImport()
  Dim lngImport     As Long
  Dim lngItems      As Long
  Dim strCol        As String

  If Not gwsNewHeader Is Nothing Then
    Application.ScreenUpdating = False
    tblResult.UsedRange.ClearContents
    tblQuery.Range("A1:U1").Copy
    With tblResult.Range("A1:U1")
        .PasteSpecial Paste:=xlPasteValues, _
                      Operation:=xlNone, _
                      SkipBlanks:=False, _
                      Transpose:=False
        .PasteSpecial Paste:=xlPasteFormats, _
                      Operation:=xlNone, _
                      SkipBlanks:=False, _
                      Transpose:=False
    End With
    Application.CutCopyMode = False
   
    With tblAdmin
      For lngImport = 2 To .Cells(Rows.Count, 19).End(xlUp).Row
        With .Range("T" & lngImport)
          If InStr(1, .Value, ":") > 0 Then
            strCol = Left(.Value, InStr(1, .Value, ":") - 1)
          Else
            strCol = .Value
          End If
        End With
        lngItems = gwsNewHeader.Range(strCol & Rows.Count).End(xlUp).Row
        gwsNewHeader.Range(strCol & 1).Resize(lngItems, 1).Copy tblResult.Cells(1, lngImport - 1)
      Next lngImport
    End With
 
    gwkbImport.Close SaveChanges:=False
    Application.ScreenUpdating = True
 
    With tblAdmin
      .Range("P2", .Cells(.Rows.Count, "P").End(xlUp)).ClearContents
      .Range("S2", .Cells(.Rows.Count, "S").End(xlUp)).ClearContents
      .Range("R1").ClearContents
    End With
  End If
  Application.Goto ThisWorkbook.Worksheets("Input").Range("A1"), Scroll:=True
  
  Set gwsNewHeader = Nothing
  Set gwkbImport = Nothing
 
End Sub

Code for module modStartUF:

VBA Code:
Public gwkbImport As Workbook
Public gwsNewHeader As Worksheet
'

Sub Call_UF()

  UserForm1.Show

End Sub

Please find the altered workbook MrE_1612814 1220041 Upload 221025

I had several runs with the sample file you supplied but no error was raised. Now I'm waiting to see what will happen on your side.

Ciao,
Holger
Hi Holger,

At the outset your latest file did run without any issues, let me try again with real data, and will let you know.

Thanks
 
Upvote 0
Hi bcmk29,

good to hear that at least the run with the test data was okay.

A couple of questions and remarks came up to me, let me put them up. The Numbers are only for having an oriantation, they do not stand for importance.

1. In cmdAdd you wanted Listboxes to be added but there is no further code indicated that should be used by these new LBs. From what I understand I would rather use Labels and add the Caption to these from Sheet3 starting with U10. Altered code may look like

VBA Code:
      Set objNewLB = Me.Controls.Add("Forms.label.1", True)
      With objNewLB
        .Name = "Label" & glngAddCtrls + 9
        .Left = 30
        .Height = 22
        .Width = 108
        .Top = lngUFHeight + (25 * glngAddCtrls)
        .Caption = tblAdmin.Range("U" & glngAddCtrls + 9).Value
      End With

As you can spot from the code I changed the static variable to a public one as I would use that in cmdProc as well.


2. Although this is a minor I would check the number of the imported headers to equal or exceed 8 for both cmdAdd and cmdProc, otherwise you will run into trouble when trying to import the data. Start of code for cmdAdd may look like

VBA Code:
  lngLR_P = tblAdmin.Cells(tblAdmin.Rows.Count, 16).End(xlUp).Row
  lngLR_U = tblAdmin.Cells(tblAdmin.Rows.Count, 21).End(xlUp).Row

  If lngLR_P >= 9 + glngAddCtrls Then
    If cblnHaHoBe Then

while at the end this code would be entered

VBA Code:
    End If
  Else
    MsgBox "Please check the data in '" & gwkbImport.FullName & vbCrLf & _
            "as the number of Headers to import does not equal at least '" & _
            8 + glngAddCtrls, vbInformation, "Not enough data"
    Unload Me
  End If

3. Right now the comboboxes are left as default. This means that any item from the list may be chosen but as well you may insert any text you want. I would recommend to limit the use to just choose items form the list. Code should be altered in UserForm_Activate

VBA Code:
  For Each objCtrl In Me.Controls
    If TypeOf objCtrl Is MSForms.ComboBox Then
      objCtrl.List = rng2List.Value
      objCtrl.Style = 2
    End If
  Next objCtrl

and cmdAdd_Click

VBA Code:
      With objNewCB
        .Name = "Combobox" & glngAddCtrls
        .Left = 168
        .Height = 22
        .Width = 108
        .Style = 2
        .Top = lngUFHeight + (25 * glngAddCtrls)
        .RowSource = tblAdmin.Name & "!P2:P" & lngLR_P
      End With

The long 2 used here stands for frmStyleDropDownList, the default is 0 or frmStyleDropDownCombo.

4. Up to now you may close the UserForm via X on the right upper top. But as you want to unload the UserForm before calling DataImport any code for cleaning up would be in the wrong place directly behind the userForm (my point of view, I may be totally wrong here). So I added a new public variable gblnCleanUp which is switched to True at the begin of UserForm_Initialize. I added a new procedure to the UserForm

VBA Code:
Private Sub UserForm_Terminate()

  Call CleanUp

End Sub

and one in modStartUF

VBA Code:
Sub CleanUp()
  If gblnCleanUp Then
    gwkbImport.Close False
    Set gwsNewHeader = Nothing
    Set gwkbImport = Nothing
    gblnCleanUp = False
    With tblAdmin
      .Range("P2", .Cells(.Rows.Count, "P").End(xlUp)).ClearContents
      .Range("S2", .Cells(.Rows.Count, "S").End(xlUp)).ClearContents
      .Range("R1").ClearContents
    End With
  End If
  Application.GoTo ThisWorkbook.Worksheets("Input").Range("A1"), Scroll:=True
End Sub

And to top all this the code at the end of cmdProc needs to be changed as of now the public variables would be cut

VBA Code:
    If blnComplete Then
      Err.Clear
      On Error GoTo 0
      With tblAdmin
        .Range("S2", .Range("S" & .Rows.Count).End(xlUp)).ClearContents
        For lngCounter = 1 To objColNoDupes.Count
          .Range("S" & lngCounter + 1).Value = objColNoDupes(lngCounter)
        Next lngCounter
      End With
      gblnCleanUp = False
      Unload Me
      Call DataImport
    End If

5. You apply formulas in Sheet3 to get the Information about the columns. This may be done by VBA using WorksheetFunction.VLookUp.

6. The check for the information about the Column Letters isn't foolproof as you may insert a cell address like A32 which would be accepted.

You may download the updated workbook MrE_1612814 1220041 Upload 221026.xlsm

Ciao,
Hiolger
 
Upvote 0
Solution
Hi bcmk29,

good to hear that at least the run with the test data was okay.

A couple of questions and remarks came up to me, let me put them up. The Numbers are only for having an oriantation, they do not stand for importance.

1. In cmdAdd you wanted Listboxes to be added but there is no further code indicated that should be used by these new LBs. From what I understand I would rather use Labels and add the Caption to these from Sheet3 starting with U10. Altered code may look like

VBA Code:
      Set objNewLB = Me.Controls.Add("Forms.label.1", True)
      With objNewLB
        .Name = "Label" & glngAddCtrls + 9
        .Left = 30
        .Height = 22
        .Width = 108
        .Top = lngUFHeight + (25 * glngAddCtrls)
        .Caption = tblAdmin.Range("U" & glngAddCtrls + 9).Value
      End With

As you can spot from the code I changed the static variable to a public one as I would use that in cmdProc as well.


2. Although this is a minor I would check the number of the imported headers to equal or exceed 8 for both cmdAdd and cmdProc, otherwise you will run into trouble when trying to import the data. Start of code for cmdAdd may look like

VBA Code:
  lngLR_P = tblAdmin.Cells(tblAdmin.Rows.Count, 16).End(xlUp).Row
  lngLR_U = tblAdmin.Cells(tblAdmin.Rows.Count, 21).End(xlUp).Row

  If lngLR_P >= 9 + glngAddCtrls Then
    If cblnHaHoBe Then

while at the end this code would be entered

VBA Code:
    End If
  Else
    MsgBox "Please check the data in '" & gwkbImport.FullName & vbCrLf & _
            "as the number of Headers to import does not equal at least '" & _
            8 + glngAddCtrls, vbInformation, "Not enough data"
    Unload Me
  End If

3. Right now the comboboxes are left as default. This means that any item from the list may be chosen but as well you may insert any text you want. I would recommend to limit the use to just choose items form the list. Code should be altered in UserForm_Activate

VBA Code:
  For Each objCtrl In Me.Controls
    If TypeOf objCtrl Is MSForms.ComboBox Then
      objCtrl.List = rng2List.Value
      objCtrl.Style = 2
    End If
  Next objCtrl

and cmdAdd_Click

VBA Code:
      With objNewCB
        .Name = "Combobox" & glngAddCtrls
        .Left = 168
        .Height = 22
        .Width = 108
        .Style = 2
        .Top = lngUFHeight + (25 * glngAddCtrls)
        .RowSource = tblAdmin.Name & "!P2:P" & lngLR_P
      End With

The long 2 used here stands for frmStyleDropDownList, the default is 0 or frmStyleDropDownCombo.

4. Up to now you may close the UserForm via X on the right upper top. But as you want to unload the UserForm before calling DataImport any code for cleaning up would be in the wrong place directly behind the userForm (my point of view, I may be totally wrong here). So I added a new public variable gblnCleanUp which is switched to True at the begin of UserForm_Initialize. I added a new procedure to the UserForm

VBA Code:
Private Sub UserForm_Terminate()

  Call CleanUp

End Sub

and one in modStartUF

VBA Code:
Sub CleanUp()
  If gblnCleanUp Then
    gwkbImport.Close False
    Set gwsNewHeader = Nothing
    Set gwkbImport = Nothing
    gblnCleanUp = False
    With tblAdmin
      .Range("P2", .Cells(.Rows.Count, "P").End(xlUp)).ClearContents
      .Range("S2", .Cells(.Rows.Count, "S").End(xlUp)).ClearContents
      .Range("R1").ClearContents
    End With
  End If
  Application.GoTo ThisWorkbook.Worksheets("Input").Range("A1"), Scroll:=True
End Sub

And to top all this the code at the end of cmdProc needs to be changed as of now the public variables would be cut

VBA Code:
    If blnComplete Then
      Err.Clear
      On Error GoTo 0
      With tblAdmin
        .Range("S2", .Range("S" & .Rows.Count).End(xlUp)).ClearContents
        For lngCounter = 1 To objColNoDupes.Count
          .Range("S" & lngCounter + 1).Value = objColNoDupes(lngCounter)
        Next lngCounter
      End With
      gblnCleanUp = False
      Unload Me
      Call DataImport
    End If

5. You apply formulas in Sheet3 to get the Information about the columns. This may be done by VBA using WorksheetFunction.VLookUp.

6. The check for the information about the Column Letters isn't foolproof as you may insert a cell address like A32 which would be accepted.

You may download the updated workbook MrE_1612814 1220041 Upload 221026.xlsm

Ciao,
Hiolger
Hi Holger, Thanks for taking time and helping me on this. Your latest file works as I expected with few corrections. I appreciate your effort on this.
Once again thanks.
 
Upvote 0
Hi bcmk29,

glad we got the code to work this far, thanks for the feedback.

Finally there is one aspect I ran into when thoroughly testing. Everything is fine while any user will only do whatever is planned to be done. But if the import file is closed before procedure DataImport is called the check I included will fail: the object will no longer exist and create a run-time error..

If you can deny that scenario to be of any relevance we're done. If you think this must be fixed and you can't solve it on your own please come back - my idea at present is to save both informations and check at the beginning of cmdProc to make sure the import workbook is open and objects are set as DataImport is called at the end of the procedure.

Ciao,
Holger
 
Upvote 0
Hi bcmk29,

glad we got the code to work this far, thanks for the feedback.

Finally there is one aspect I ran into when thoroughly testing. Everything is fine while any user will only do whatever is planned to be done. But if the import file is closed before procedure DataImport is called the check I included will fail: the object will no longer exist and create a run-time error..

If you can deny that scenario to be of any relevance we're done. If you think this must be fixed and you can't solve it on your own please come back - my idea at present is to save both informations and check at the beginning of cmdProc to make sure the import workbook is open and objects are set as DataImport is called at the end of the procedure.

Ciao,
Holger
Holger,

I got your point but haven't implemented it yet. I need your help with the below.

1. While importing the header I realized the import workbook has blank columns and the tool currently imports as is in tblAdmin P2. This also replicates in the Combobox for user selection.
I need to get only the Headers of the Column with Data. Please advice.
2. If there is a header without data in the import file, I should allow the user to select a duplicate value in the userform. Right now the code restricts entering an identical value. This also impacts gathering the selected value for tblAdmin S2. Please advice.

Thanks.
 
Upvote 0
Hi bcmk29,

regarding #1 the codelines in question are

VBA Code:
  If blnUnload = False Then
    tblAdmin.Range("P2:P" & tblAdmin.Rows.Count).ClearContents
    varArr = gwsNewheader.Range("A1").Resize(1, gwsNewheader.Cells(1, Columns.Count).End(xlToLeft).Column)
    varArr = WorksheetFunction.Transpose(varArr)
    tblAdmin.Range("P2").Resize(UBound(varArr), 1).Value = varArr
    Application.Goto tblAdmin.Range("P1"), True
  End If

And I understand

I need to get only the Headers of the Column with Data.

Not a great deal as we could have to use a loop instead of an array to copy if data is present. I'm not so sure about the letters in Column Q to fit as I don't have all the necessary code in ind.

Regarding #2: it was my decision to work with a dictionary which will only allow one value for each ComboBox (I am no fan of saving the same data in different locations). If you want to go the way of letting any a header be chosen more than once it's okay but we should restrict the number of choices (I would suggest limit it to 2 as any user with the normal number of ComboBoxes could use only 4 different items which somehow doesn't feel to good for me). Please tell me how you want this to be handled.
I could imagine to use an entry maybe called Dummy for the CB and adjust the code to skip the cell with Dummy but haven't thoroughly thought on that.

Ciao,
Holger
 
Last edited:
Upvote 0
Hi bcmk29,

regarding #1 the codelines in question are

VBA Code:
  If blnUnload = False Then
    tblAdmin.Range("P2:P" & tblAdmin.Rows.Count).ClearContents
    varArr = gwsNewheader.Range("A1").Resize(1, gwsNewheader.Cells(1, Columns.Count).End(xlToLeft).Column)
    varArr = WorksheetFunction.Transpose(varArr)
    tblAdmin.Range("P2").Resize(UBound(varArr), 1).Value = varArr
    Application.Goto tblAdmin.Range("P1"), True
  End If

And I understand



Not a great deal as we could have to use a loop instead of an array to copy if data is present. I'm not so sure about the letters in Column Q to fit as I don't have all the necessary code in ind.

Regarding #2: it was my decision to work with a dictionary which will only allow one value for each ComboBox (I am no fan of saving the same data in different locations). If you want to go the way of letting any a header be chosen more than once it's okay but we should restrict the number of choices (I would suggest limit it to 2 as any user with the normal number of ComboBoxes could use only 4 different items which somehow doesn't feel to good for me). Please tell me how you want this to be handled.
I could imagine to use an entry maybe called Dummy for the CB and adjust the code to skip the cell with Dummy but haven't thoroughly thought on that.

Ciao,
Holger
Holger,

I tried to create/modify the codes as you mentioned for both items but ran into trouble, If you can modify the code for me that will be a great help.
Allowing 2 duplicates will solve my need for now.

Thanks.
 
Upvote 0
Hi bcmk29,

new modulewide Variables for the UserForm, Errorhandler added for all procedures.

UserForm_Initialize: filling of modulewide variables added, changed the array from getting the header names to getting both header names and column letter.
cmdAdd: shortened code to just work with UF from uploaded workbook
cmdProc: instead of using a dictionary which woud only allow unique items applied 2 arrays to hold the uniques and all headers. Maximum number of duplicates (not for single items but overall) as constant. Integrated check for the workbook with new data still to be opened.
DataImport: code slightly adapted for the use of column letter

Code behind the UserForm:

VBA Code:
Dim mstrFullNameWB    As String
Dim mstrNameWB        As String
Dim mstrNameWS        As String
'

Private Sub UserForm_Initialize()
  Dim lngIndexWS      As Long       'index of worksheet in new workbook if more than one worksheet
  Dim lngWS           As Long       'counter for index of worksheets in opened workbook
  Dim varFile         As Variant    'variable to hold path and filename for workbook to open
  Dim varArr()        As Variant    'values for the header values to be copied
  Dim strWS           As String     'Holding the names of worksheets of new workbook
  Dim ws              As Worksheet  'for looping worksheets in new workbook
  Dim wb              As Workbook   'for looping through all open workbooks
  Dim blnRunOnce      As Boolean    'boolean for getting information about worksheets,
  Dim blnUnload       As Boolean    'boolean whether to unload the UF
  Dim lngColMax       As Long
  Dim lngCounter      As Long
  Dim lngArr          As Long
  Dim strAddress      As String
  
  Const cstrProcName  As String = "UserForm1_Initialize"
  Const cblnBcmk      As Boolean = False
  
  On Error GoTo err_here
  blnUnload = False
  gblnCleanUp = True
  
  If tblInput.Cells(Rows.Count, 1).End(xlUp).Row <> 1 Then GoTo end_here
  
  If gwkbImport Is Nothing Then
    varFile = Application.GetOpenFilename("(*.xlsx),", MultiSelect:=False)
    If varFile = False Then
      MsgBox "No file selected to import.", 48
      blnUnload = True
      GoTo end_here
    End If
    Set gwkbImport = Workbooks.Open(Filename:=varFile)
  Else
    For Each wb In Workbooks
      If wb.Name = gwkbImport.Name Then Exit For
    Next wb
    Set gwkbImport = Workbooks.Open(Filename:=varFile)
  End If
  mstrFullNameWB = gwkbImport.FullName
  mstrNameWB = gwkbImport.Name
  
  If cblnBcmk Then MsgBox gwkbImport.FullName
  If gwsNewheader Is Nothing Then
    If gwkbImport.Worksheets.Count > 1 Then
      blnRunOnce = False
reIB:
      If blnRunOnce = False Then
        For Each ws In gwkbImport.Worksheets
          lngWS = lngWS + 1
          strWS = strWS & lngWS & " : " & ws.Name & vbCrLf
        Next ws
        blnRunOnce = True
      End If
      lngIndexWS = Application.InputBox("Enter worksheet number" & vbCrLf & Left(strWS, Len(strWS) - 1), "Worksheet selection", , , , , , 1)
      If lngIndexWS > gwkbImport.Worksheets.Count Then
        MsgBox "Invalid Worksheet Input, Try Again.", 48, "Entry Required"
        GoTo reIB
      ElseIf lngIndexWS = 0 Then
        MsgBox "Procedure cancelled", vbInformation, "Stopping here"
        gwkbImport.Close False
        Set gwkbImport = Nothing
        blnUnload = True
        GoTo end_here
      Else
        Set gwsNewheader = gwkbImport.Worksheets(lngIndexWS)
      End If
    Else
      Set gwsNewheader = gwkbImport.Worksheets(1)
    End If
  End If
  mstrNameWS = gwsNewheader.Name

  Err.Clear
  On Error GoTo 0
  If blnUnload = False Then
    tblAdmin.Range("P2:P" & tblAdmin.Rows.Count).ClearContents
    With gwsNewheader
      lngColMax = .Cells(1, Columns.Count).End(xlToLeft).Column
      lngArr = lngColMax - WorksheetFunction.CountBlank(.Range(.Cells(2, 1), .Cells(2, lngColMax)))
      ReDim varArr(1 To lngArr, 1 To 2)
      lngArr = 0
      For lngCounter = 1 To lngColMax
        If WorksheetFunction.CountBlank(.Range(.Cells(2, lngCounter), .Cells(4, lngCounter))) = 0 Then
          lngArr = lngArr + 1
          With .Cells(1, lngCounter)
            varArr(lngArr, 1) = .Value
            strAddress = Left(.Address(0, 0), Len(.Address(0, 0)) - 1)
            varArr(lngArr, 2) = strAddress '& ":" & strAddress
          End With
        End If
      Next lngCounter
    End With
    tblAdmin.Range("P2").Resize(UBound(varArr, 1), 2).Value = varArr
    Erase varArr
    Application.Goto tblAdmin.Range("P1"), True
  End If

end_here:
  Err.Clear
  On Error GoTo 0
  If blnUnload Then End
  Exit Sub

err_here:
  Debug.Print "Actual procedure name: " & cstrProcName & vbCrLf & _
              "Error number: " & Err.Number & vbCrLf & _
              "Error description: " & Err.Description
  Err.Clear
  On Error GoTo 0
  Resume end_here

End Sub

Private Sub UserForm_Activate()
  Dim rng2List        As Range          'object holding range for List for CBs
  Dim objCtrl         As Control        'object to cycle through the Controls on the UF
  
  Const cstrProcName  As String = "UserForm1_Activate"
  
  On Error GoTo err_here
  glngAddCtrls = 0
  Set rng2List = tblAdmin.Range("P2", tblAdmin.Cells(Rows.Count, 16).End(xlUp))
  
  For Each objCtrl In Me.Controls
    If TypeOf objCtrl Is MSForms.ComboBox Then
      objCtrl.List = rng2List.Value
      objCtrl.Style = 2
    End If
  Next objCtrl
  
  Application.Goto tblInput.Range("A1"), True
  
end_here:
  Set rng2List = Nothing
  On Error GoTo 0
  Exit Sub

err_here:
  Debug.Print "Actual procedure name: " & cstrProcName & vbCrLf & _
              "Error number: " & Err.Number & vbCrLf & _
              "Error description: " & Err.Description
  Err.Clear
  On Error GoTo 0
  Resume end_here
  
End Sub

Private Sub cmdAdd_Click()
  Dim objNewLB        As Object
  Dim objNewCB        As Object
  Dim lngUFHeight     As Long
  Dim lngLR_P         As Long
  Dim lngLR_U         As Long
  
  Const cstrProcName  As String = "cmdAdd_Click"
  
  On Error GoTo err_here
  
  lngLR_P = tblAdmin.Cells(tblAdmin.Rows.Count, 16).End(xlUp).Row
  lngLR_U = tblAdmin.Cells(tblAdmin.Rows.Count, 21).End(xlUp).Row

  If lngLR_P >= 9 + glngAddCtrls Then
    glngAddCtrls = glngAddCtrls + 1
    Me.Height = Me.Height + (30 * glngAddCtrls)
    lngUFHeight = 230
    Set objNewLB = Me.Controls.Add("Forms.label.1", True)
    With objNewLB
      .Name = "Label" & glngAddCtrls + 9
      .Left = 30
      .Height = 22
      .Width = 108
      .Top = lngUFHeight + (25 * glngAddCtrls)
      .Caption = tblAdmin.Range("U" & glngAddCtrls + 9).Value
    End With
    Set objNewCB = Me.Controls.Add("Forms.combobox.1", True)
    With objNewCB
      .Name = "Combobox" & glngAddCtrls
      .Left = 168
      .Height = 22
      .Width = 108
      .Style = 2
      .Top = lngUFHeight + (25 * glngAddCtrls)
      .RowSource = tblAdmin.Name & "!P2:P" & lngLR_P
    End With
    With cmdAdd
      .Left = 30
      .Top = lngUFHeight + 5 + (25 * (glngAddCtrls + 2))
    End With
    With cmdProc
      .Left = 168
      .Top = lngUFHeight + 5 + (25 * (glngAddCtrls + 2))
    End With
    With Label9
      .Left = 30
      .Top = lngUFHeight + (30 * (glngAddCtrls + 1))
      If glngAddCtrls > 0 Then
        .Caption = glngAddCtrls & " Fields Added"
      End If
    End With
  Else
    MsgBox "Please check the data in '" & gwkbImport.FullName & vbCrLf & _
            "as the number of Headers to import does not equal at least '" & _
            8 + glngAddCtrls, vbInformation, "Not enough data"
    Unload Me
  End If

end_here:
  On Error GoTo 0
  Exit Sub

err_here:
  Debug.Print "Actual procedure name: " & cstrProcName & vbCrLf & _
              "Error number: " & Err.Number & vbCrLf & _
              "Error description: " & Err.Description
  Err.Clear
  On Error GoTo 0
  Resume end_here

End Sub

Private Sub cmdProc_Click()
  Dim blnComplete       As Boolean
  Dim blnWBCheck        As Boolean
  Dim objCtrl           As Control
  Dim lngCounter        As Long
  Dim lngUnique         As Long
  Dim lngAll            As Long
  Dim lngDouble         As Long
  Dim varUnique()       As Variant
  Dim varAll()          As Variant
  Dim wb                As Workbook

  Const clngMaxDoubles  As Long = 2
  Const cstrProcName    As String = "cmdProc_Click"
  
  On Error GoTo err_here
  
  ReDim varUnique(1 To 1)
  ReDim varAll(1 To 1)
  
  If tblAdmin.Cells(tblAdmin.Rows.Count, 16).End(xlUp).Row >= 9 + glngAddCtrls Then
    For Each objCtrl In Me.Controls
      If TypeOf objCtrl Is MSForms.ComboBox Then
        With objCtrl
          blnComplete = Len(.Value) > 0
          If blnComplete Then
            lngAll = lngAll + 1
            ReDim Preserve varAll(1 To lngAll)
            varAll(lngAll) = .Value
            If IsError(Application.Match(.Value, varUnique, 0)) Then
              lngUnique = lngUnique + 1
              ReDim Preserve varUnique(1 To lngUnique)
              varUnique(lngUnique) = .Value
            Else
              lngDouble = lngDouble + 1
              If lngDouble = clngMaxDoubles Then
                Select Case MsgBox("Max of items to duplicate reached." & vbCrLf & _
                      "Ignore - Continue" & vbCrLf & _
                      "Retry - Change Item" & vbCrLf & _
                      "Abort - End Process", vbAbortRetryIgnore, "What to do?")
                  Case vbIgnore
                    Exit For
                  Case vbRetry
                    .SetFocus
                    GoTo end_here
                  Case vbAbort
                    GoTo end_here
                End Select
              End If
            End If
          Else
            MsgBox "Please fill blank field", 48, "Entry Required"
            .SetFocus
            GoTo end_here
          End If
        End With
      End If
      Err.Clear
      On Error GoTo 0
    Next objCtrl
    
    If blnComplete Then
      Err.Clear
      On Error GoTo 0
      With tblAdmin
        .Range("S2", .Range("S" & .Rows.Count).End(xlUp)).ClearContents
        .Range("S2").Resize(UBound(varAll), 1).Value = WorksheetFunction.Transpose(varAll)
      End With
      For Each wb In Workbooks
        If wb.Name = mstrNameWB Then
          blnWBCheck = True
          Exit For
        End If
      Next wb
      If blnWBCheck = False Then
        Set gwkbImport = Workbooks.Open(mstrFullNameWB)
        Set gwsNewheader = gwkbImport.Sheets(mstrNameWS)
      End If
      gblnCleanUp = False
      Unload Me
      Call DataImport
    End If
  Else
    MsgBox "Please check the data in '" & mstrFullNameWB & vbCrLf & _
            "as the number of Headers to import does not equal at least '" & _
            8 + glngAddCtrls, vbInformation, "Not enough data"
    Unload Me
  End If

end_here:
  Erase varUnique
  Erase varAll
  Err.Clear
  On Error GoTo 0
  Exit Sub

err_here:
  Debug.Print "Actual procedure name: " & cstrProcName & vbCrLf & _
              "Error number: " & Err.Number & vbCrLf & _
              "Error description: " & Err.Description
  Err.Clear
  On Error GoTo 0
  Resume end_here

End Sub

Private Sub UserForm_Terminate()

  Call CleanUp

End Sub

Module modDataImport:

VBA Code:
Sub DataImport()
  Dim lngImport       As Long
  Dim lngItems        As Long
  Dim strCol          As String
    
  Const cstrProcName  As String = "DataImport"
  
  On Error GoTo err_here
  Application.ScreenUpdating = False
  tblResult.UsedRange.ClearContents
  tblQuery.Range("A1:U1").Copy
  With tblResult.Range("A1:U1")
      .PasteSpecial Paste:=xlPasteValues, _
                    Operation:=xlNone, _
                    SkipBlanks:=False, _
                    Transpose:=False
      .PasteSpecial Paste:=xlPasteFormats, _
                    Operation:=xlNone, _
                    SkipBlanks:=False, _
                    Transpose:=False
  End With
  
  With tblAdmin
    For lngImport = 2 To .Cells(Rows.Count, 19).End(xlUp).Row
      strCol = .Range("T" & lngImport).Value
      lngItems = gwsNewheader.Range(strCol & Rows.Count).End(xlUp).Row
      gwsNewheader.Range(strCol & 1).Resize(lngItems, 1).Copy tblResult.Cells(1, lngImport - 1)
    Next lngImport
  End With
  
  gwkbImport.Close SaveChanges:=False
  Application.ScreenUpdating = True
  
  With tblAdmin
    .Range("P2", .Cells(.Rows.Count, "Q").End(xlUp)).ClearContents
    .Range("S2", .Cells(.Rows.Count, "S").End(xlUp)).ClearContents
    .Range("R1").ClearContents
  End With
  Application.Goto ThisWorkbook.Worksheets("Input").Range("A1"), Scroll:=True
   
end_here:
  Set gwsNewheader = Nothing
  Set gwkbImport = Nothing
  Err.Clear
  On Error GoTo 0
  Exit Sub

err_here:
  Debug.Print "Actual procedure name: " & cstrProcName & vbCrLf & _
              "Error number: " & Err.Number & vbCrLf & _
              "Error description: " & Err.Description
  Err.Clear
  On Error GoTo 0
  Resume end_here
 
End Sub

Module modStartUF:

VBA Code:
Public gwkbImport As Workbook
Public gwsNewheader As Worksheet
Public gblnCleanUp As Boolean
Public glngAddCtrls As Long
'

Sub Call_UF()

  UserForm1.Show 'vbModeless

End Sub

Sub CleanUp()
  If gblnCleanUp Then
    gwkbImport.Close False
    Set gwsNewheader = Nothing
    Set gwkbImport = Nothing
    gblnCleanUp = False
    With tblAdmin
      .Range("P2", .Cells(.Rows.Count, "Q").End(xlUp)).ClearContents
      .Range("S2", .Cells(.Rows.Count, "S").End(xlUp)).ClearContents
      .Range("R1").ClearContents
    End With
  End If
  Application.Goto ThisWorkbook.Worksheets("Input").Range("A1"), Scroll:=True
End Sub

ThisWorkbook/DieseArbeitsmappe:

VBA Code:
Private Sub Workbook_Open()
  Application.Goto tblInput.Range("G4"), False
End Sub

Link: MrE_1612814 1220041 Upload 221029.xlsm

Ciao,
Holger
 
Upvote 0

Forum statistics

Threads
1,224,823
Messages
6,181,181
Members
453,022
Latest member
Mohamed Magdi Tawfiq Emam

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top