1

I am setting up VBA code which does the following when run:

  1. Runs a loop to open Excel files in a folder, one by one
  2. Every time that an Excel file is opened, a password unprotects the worksheet and unmerges cells
  3. Once the cells are unmerged, the data from the Excel file is copied and pasted to specific cells in the workbook where the VBA code is originally saved/stored
  4. Upon pasting the data, the opened Excel workbook from the loop now closes (not necessary to save), and the next workbook is opened, where the next set of data is placed one row below the previous row

The VBA code is run from a workbook which always remains open, we can call it "Workbook 1.xlsm" In this instance for the code below, the use of wbPaste as the active workbook is intended to reference "Workbook 1.xlsm". Because the name of the workbook is going to change every month that this is run, I wanted to declare a workbook by using a naming convention that would reference the name, regardless of what the workbook is called.

The files that are in the folder can have various names, and could be in the hundreds of total files. I have declared most of the variables and have had success in getting the Excel workbooks to open from the folder. Unprotecting the sheet, and unmerging the cells has given some problems, however. I think that the issue that I am experiencing comes with looping the opening of the workbooks and which workbook is considered "active" at the time.

    Sub OpenFilesForExtraction()


    'declaration of variables
    Dim myFolder As String
    Dim myFile As String
    Dim wbCopy As Workbook
    Dim wbPaste As Workbook
    Dim lastRow As Long


    'setting up name of folder and file type (any Excel file in folder) for the loop
    myFolder = "C:\Users\Me\Desktop\Folder 1\"
    myFile = Dir(myFolder & "*.xl??")
    lastRow = 3

    'start of loop
    Do While myFile <> ""

    Workbooks.Open fileName:=myFolder & myFile


    'wbCopy is the Excel file that gets unprotected, unmerged and data is copied from. wbPaste will be where the data gets copied to.  wbPaste is referencing the workbook where the macro is stored.  By declaring these files in the loop, wbCopy should take on the name of the next file opening from the folder

     Set wbCopy = Workbooks(myFile)
     Set wbPaste = ActiveWorkbook


    'Unprotecting and unmerging from the file wbCopy, that was opened by the loop statement

         wbCopy.Unprotect Password:="Password1"
         wbCopy.Unprotect
         Range("C15:E15").Select
         Selection.UnMerge
         Range("H15:J15").Select
         Selection.UnMerge
         Range("C17:E17").Select
         Selection.UnMerge
         Range("B23:C23").Select
         Selection.UnMerge
         Range("B29:C29").Select
         Selection.UnMerge
         Range("B31:J37").Select
         Selection.UnMerge


    'Copying and pasting the information from the files that are being opened to the file wbPaste.  Note that the range for where the value is pasted is determined by the value of "lastRow" variable, which is designed to paste information starting with the cells in row 3, then moving to row 4, row 5, and so on....

    wbCopy.Range("C13").Value = wbPaste.Range("A" & lastRow).Value
    wbCopy.Range("C15").Value = wbPaste.Range("B" & lastRow).Value
    wbCopy.Range("H15").Value = wbPaste.Range("D" & lastRow).Value
    wbCopy.Range("C17").Value = wbPaste.Range("I" & lastRow).Value
    wbCopy.Range("J17").Value = wbPaste.Range("H" & lastRow).Value

    wbCopy.Close


    lastRow = lastRow + 1

    myFile = Dir


    Loop

    End Sub

The program reaches a point where it will open up the first file from the folder, however, I get an immediate error after that. I think that there are two potential reasons.

First, I am not certain if I should use anything related to ActiveWorkbook. The reason why is because as I loop through opening the Excel documents in the folder, the VBA code may not understand which is meant to be the ActiveWorkbook at certain times.

Second, the Unmerging and copy/paste of values is where this will stop the program. I have had some chances to allow the cells to unmerge, but I think it came at the cost of calling out the wbCopy file as an ActiveWorkbook, when it really isn't meant to be called out as an active workbook.

Mathieu Guindon
  • 69,817
  • 8
  • 107
  • 235
Bux7519
  • 11
  • 1
  • You are correct in your assumption that you shouldn't use `ActiveWorkbook`. You also want to avoid using Select, see [this](https://stackoverflow.com/questions/10714251/how-to-avoid-using-select-in-excel-vba) – cybernetic.nomad Sep 26 '19 at 21:16
  • Thanks - so, based off of not wanting to use select, is it more useful to use: Range("C15:E15").UnMerge ??? I am still getting an error, which I would assume would be in relation to the idea that the Range in question may be referring to wbPaste, as opposed to wbCopy?? – Bux7519 Sep 26 '19 at 21:23
  • it's better to specify which workbook (and worksheet) a range is in. Something like `wbPaste.Worksheets("sheet1").Range("C5:E15").Unmerge` – cybernetic.nomad Sep 26 '19 at 21:27
  • I tried this and get a similar error to what I have received before: Run-time error '1004': Application-defined or object-defined error This is using the following code: wbCopy.Worksheets("Sheet1").Range("C5:E15").Unmerge Just to remember, the name of wbCopy are all workbooks that the data must be copied from. wbPaste is where I would run the VBA script out of, and all data is pasted from wbCopy into wbPaste. This is where I think I have an issue with my code, because I feel as if though the code won't recognize the "active" workbook in some cases. – Bux7519 Sep 26 '19 at 21:37
  • Syntactically, is the code doing what it is intending to do? – Bux7519 Sep 26 '19 at 21:41
  • You should always assume the code has no idea what the active workbook is. That is why you should always specify what workbook and worksheet a range is in – cybernetic.nomad Sep 26 '19 at 21:44

1 Answers1

1

There are a number of issues here

  1. Relying on ActiveWorkbook when opening books changes what's active
  2. Using Select
  3. Your copy/paste is reversed
  4. Unnecessary second Unprotect
  5. Not using ThisWorkbook (you say you specifically want to paste into the book containing the VBA code)
  6. Refering to Range's on Workbooks, instead of Worksheets

Your code, refactored

Sub OpenFilesForExtraction()
    'declaration of variables
    Dim myFolder As String
    Dim myFile As String
    Dim wbCopy As Workbook
    Dim wsCopy As Worksheet
    Dim wsPaste As Worksheet
    Dim lastRow As Long

    'setting up name of folder and file type (any Excel file in folder) for the loop
    myFolder = "C:\Users\Me\Desktop\Folder 1\"
    myFile = Dir(myFolder & "*.xl??")
    lastRow = 3

    'start of loop
    Set wsPaste = ThisWorkbook.Worksheets("NameOfSheetToPasteOn")

    Do While myFile <> vbNullString
        'wbCopy is the Excel file that gets unprotected, unmerged and data is copied from. wbPaste will be where the data gets copied to.  wbPaste is referencing the workbook where the macro is stored.  By declaring these files in the loop, wbCopy should take on the name of the next file opening from the folder
        Set wbCopy = Workbooks.Open(Filename:=myFolder & myFile)

        'Unprotecting and unmerging from the file wbCopy, that was opened by the loop statement
        wbCopy.Unprotect Password:="Password1"
        Set wsCopy = wbCopy.Worksheets("NameOfSheetToCopyFrom")
        With wsCopy
            'wbCopy.Unprotect
            .Range("C15:E15").UnMerge
            .Range("H15:J15").UnMerge
            .Range("C17:E17").UnMerge
            .Range("B23:C23").UnMerge
            .Range("B29:C29").UnMerge
            .Range("B31:J37").UnMerge

            'Copying and pasting the information from the files that are being opened to the file wbPaste.
            'Note that the range for where the value is pasted is determined by the value of "lastRow" variable,
            'which is designed to paste information starting with the cells in row 3, then moving to row 4, row 5, and so on....
            wsPaste.Range("A" & lastRow).Value = .Range("C13").Value
            wsPaste.Range("B" & lastRow).Value = .Range("C15").Value
            wsPaste.Range("D" & lastRow).Value = .Range("H15").Value
            wsPaste.Range("I" & lastRow).Value = .Range("C17").Value
            wsPaste.Range("H" & lastRow).Value = .Range("J17").Value

        End With
        wbCopy.Close False

        lastRow = lastRow + 1

        myFile = Dir
    Loop

End Sub
chris neilsen
  • 52,446
  • 10
  • 84
  • 123
  • First of all, thank you chris. I am new to coding in VBA, so I might confuse some statements in code. I am looking through this now to learn and see what results I get. Will come back with any questions that I may have. Thank you again. – Bux7519 Sep 27 '19 at 13:54
  • So, I am receiving **Run-time error '1004': Application-defined or object defined error**
    This is occurring on the lines where the code is unmerging the cells C15:E15. The use of the with statement makes sense, but I wonder if the code for wbCopy opening the workbook and then declaring wsCopy as those worksheets is trying to re-open a book that is already open?
    – Bux7519 Sep 27 '19 at 15:07
  • So my concern with using "ThisWorkbook" is because I will technically have two workbooks open at the same time. When I went into the Locals Window, I see that the wbCopy is being referenced as ThisWorkbook, and that is not the design. That is probably what is creating the error. wbCopy, while open, is not designed to be the active workbook. The active workbook (ThisWorkbook) would be where the data is pasted into. wsCopy and wsPaste are both referencing the same worksheet (Sheet1), which is not designed to be the case. wsCopy refers to Sheet 1, but wsPaste should refer elsewhere – Bux7519 Sep 27 '19 at 19:15
  • 1
    @bux your understanding of what ThisWorkbook is, is incorrect. Please go and read up on it in the documentation – chris neilsen Sep 28 '19 at 02:28
  • That's fine, and it is why I am asking questions about it. The code that you presented gets stuck in an error. I am unaware of the best way to fix it. The only thing that I am aware of is when I F8 through all of the lines of code, I get the following correct: myFolder, myFile and lastRow all do what they are supposed to do. However, there is a problem with the code as it stands. wbCopy becomes ThisWorkbook. wsCopy and wsPaste are referencing the same worksheet ("Sheet 1"). I am not unmerging or copying from the same reference point to the same reference point. – Bux7519 Sep 30 '19 at 14:10
  • Same error is happening on the same line. Once the With statement is run, the act of ummerging the cells creates the error. – Bux7519 Oct 01 '19 at 17:59