Inserting column in Excel 2013 Add In fails with Error 438 - vba

I would appreciate help solving this vexing problem with inserting a column into a worksheet with VBA. The worksheet is generated from a database. I need to insert a column into the worksheet for data that is not part of the database. The project takes the data from the worksheet and writes it to a series of Word forms. The code works fine when run from a module in the macro enabled worksheet. When I use the code in an Add-In (.xlam) it doesn't insert the column and an Error 438 is captured by Err.Number. When I put the module in a separate workbook and run it, the column is inserted but the error is still captured. I've tried a lot of the suggestions for debugging and fixing my code to run properly in an add-in. The add in is signed with a valid certificate which should allow it to run on our network.
I started using the .EntireColumn.Insert but switched to Selection.Insert to see it that would work. Both versions fail to insert the column. I also changed the code to create a specific reference to the target worksheet instead of relying on ActiveWorkbook or Activesheet.
Edit: The worksheets are not protected.
I was using #Rory method for Excel VBA Add In Control.
I tried #ErikEidt's answer to Standalone code for Excel to use a button on the Excel Quick Access Toolbar to run the Add-In.
I still get the error message but the code exectues and the column is inserted successfully.
Here is the relevant extract of my code.
Option Explicit
Sub FormfromExcell()
'Note:Requires Reference to Microsoft Word and Excel(15.0 for 2013)Object Library set in Tools>References
'DECLARE AND SET VARIABLES
' Excel Objects
Dim WBA As Workbook 'The Active workbook
Dim WBAname As String
Dim wksht As Worksheet 'Excel Worksheet
Dim shtName As String
Dim myLastRow As Long
Dim myLastCol As Long
' Initialize the Excel Objects
Set WBA = ActiveWorkbook 'The workbook that calls the Add-In
WBAname = ActiveWorkbook.Name
shtName = WBA.Worksheets("Dynamic Risk Report").Name
Set wksht = WBA.Worksheets("Dynamic Risk Report")
'Set wksht = Workbooks("WBAname").Worksheets("shtName")
Application.StatusBar = "Checking for Status and Action Columns"
' Check for presence of non-database columns (Action and Status) and insert them if not there.
If wksht.Cells(1, "D") = "Action" Then GoTo Checkforstatus
'wksht.Range("D1").EntireColumn.Insert
wksht.Columns("D:D").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
If Err.Number <> 0 Then MsgBox "Error" & Err.Number
wksht.Cells(1, "D").Value = "Action"
Checkforstatus:
'Rest of code

If you can eliminate the Select and just do a straight insert, will that work?
Also you try defining your own constants, just in case Add-In doesn't have access - even though that doesn't make sense to me, seeing as you're runnign this from Excel
Const xlToRight = -4161
Const xlFormatFromLeftOrAbove = 0
Dim rge As Range
Replace this:
wksht.Columns("D:D").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
With this
Set rge = wksht.Columns("D:D")
rge.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove

Related

VBA: Referencing a Worksheet in the Active Workbook

While this seems very basic, I am continually getting an error message while trying to select a cell in a certain sheet on my workbook in my Macro. Does any one know why this will not work? I'm getting error message Run Time Error '1004'.
The sheets name is "Sheet1"and my code is below:
Application.ActiveWorkbook.Worksheets("Sheet1").Range("N2").Select
It's bad practice to use ActiveWorkbook when you don't need to. It's always better to set your workbooks and worksheets to actual variables that you can call on. I think your code is activating another workbook then trying to select a range in a worksheet it can't find.
Sub TryThis()
Dim wbk As Workbook
Dim ws As Worksheet
Set wbk = Workbooks("myWorkbook.xlsm")
Set ws = wbk.Worksheets("Sheet1")
'Now when we say "ws." it is actually "Workbooks("myWorkbook.xlsm").Worksheets("Sheet1")."
'This is okay to start with but it's better to work with the cells directly
ws.Select
Range("N2").Select
Selection = "myText"
'This is much faster and you won't have to worry about what is currently selected
ws.Range("N2") = "myText"
End Sub

excel vba insert column runtime error 1004

this is my first post on StackExchange! I've been using StackExchange for answers, but now i really have a question.
I am trying to add a column in excel using vba. This is procedure is part of a bigger sub function of which I created a new workbook and copy a series of sheets from a different workbook over.
Workbooks.Add
Set TTB = ActiveWorkbook
'add a bunch of sheets here
'sheetName = specific_sheet
Set ttb_sheet = TTB.Sheets(sheetName)
ttb_sheet.Columns("I:I").Insert Shift:=xlToRight
With this i get a runtime error of 1004: 'Insert method of Range class failed'
I tried following a series of questions on StackOverflow...
Select method of Range class failed via VBA
VBA error 1004 - select method of range class failed
It seems like the solution is to select the sheet first, then select the range. I have tried this and there was no luck. Anyone have any insight?
Here's my main sub code..
Sub create_TTB_workbook(TTB_name_)
'create TTB workbook
Dim wsHelper As New WorksheetHelper
Dim final_TTB As Workbook
Dim ttb_sheet As Worksheet
ttb_wb = ActiveWorkbook.name
Workbooks(ttb_wb).Activate
PCB_tab = 0
ST_COMP_tab = 0
For Each WS In Worksheets
If WS.name = "PCB_PIN_REPORT" Then
PCB_tab = 1
End If
If WS.name = "ST_PIN_REPORT" Then
ST_COMP_tab = 1
End If
Next WS
Workbooks.Add
Set TTB = ActiveWorkbook
new_ttb_wb = TTB.name
Debug.Print (new_ttb_wb)
If PCB_tab = 1 Then
wsHelper.copySheet ttb_wb, "PCB_PIN_REPORT", new_ttb_wb, "PCB_PIN_REPORT"
End If
If ST_COMP_tab = 1 Then
wsHelper.copySheet ttb_wb, "ST_PIN_REPORT", new_ttb_wb, "ST_PIN_REPORT"
End If
wsHelper.copySheet ttb_wb, TTB_name_, new_ttb_wb, TTB_name_
' TRIED A BUNCH OF METHODS here...
'Workbooks(ttb_wb).Sheets(TTB_name_).Cells.copy
'Sheets.Add.name = TTB_name_
'ActiveSheet.paste
'Sheets(TTB_name_).Activate
'Columns("I:I").Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
'Worksheets(TTB_name_).Range("I1").EntireColumn.Insert
'Columns("I:I").Select
'Columns("I:I").Insert Shift:=xlToRight
Set ttb_sheet = Sheets(TTB_name_)
ttb_sheet.Columns("I:I").Insert Shift:=xlToRight
Columns("K").copy Destination:=Range("I1")
Range("I6") = "header name"
End Sub
Whenever I run into an issue like this, I always isolate the code to its simplest form. Once I get it working at that level, I add it back in to the full application and can usually figure out what I did wrong.
I've written a simple version of what you are trying to do. Note that I've included a few Debug.Print statements to help me verify what is going on. The debug messages will appear in your Immediate window. Obviously you can also step through the code and examine variables as you go.
To get this to work, create a workbook and save it as DestinationWorkbook.xlsx. Then open another workbook and insert the code below.
Sub InsertColumnInDestinationWorksheet()
Dim sourceWb As Workbook
Dim targetWb As Workbook
Dim sourceWs As Worksheet
Dim targetWs As Worksheet
Set sourceWb = ThisWorkbook
Debug.Print sourceWb.Name
Set targetWb = Workbooks("DestinationWorkbook.xlsx")
Debug.Print targetWb.Name
Set sourceWs = sourceWb.Sheets("Sheet1")
Debug.Print sourceWs.Name
Set targetWs = targetWb.Sheets("Sheet1")
Debug.Print targetWs.Name
targetWs.Range("I1").Value2 = "Moving right along..."
targetWs.Columns("I:I").Insert shift:=xlToRight
End Sub
After running the code, you can examine the target sheet. You should see the text we wrote into column I is now in column J.
This works for me when I change the variable naming to:
Sub testingg()
Dim ttb_sheet As Worksheet
Set ttb_sheet = Sheets(1)
ttb_sheet.Columns("I:I").Insert Shift:=xlToRight
End Sub
So I presume there's an issue with the way you reference the workbook when setting ttb_sheet on line 3. Note that you add a workbook but you aren't actually 'activating' it necessarily. And are you sure the 'Sheetname' actually exists in the TTB workbook?

Excel VBA With statement returning type mismatch

I have created some VBA code to take populated data from a spreadsheet called "Horizontal Data" and paste it into a worksheet called "master plan data", however the with Workbooks(wb1) is throwing a type mismatch error, is there anything wrong I am doing here?
Dim WBA as Variant
Dim WB1, WB2 As Workbook
Dim L As Long
Set WB2 = ThisWorkbook
MsgBox "Select Master Plan File"
WBA = Application.GetOpenFilename( _
FileFilter:="Excel Files (*.XLSX), *.XLSX", _
Title:="Select Master Plan File")
If WBA = False Then
MsgBox "You have not selected a file"
Exit Sub
End If
Set WB1 = Workbooks.Open(WBA)
WB2.Activate
With Worksheets("Master Plan Data")
.Rows("2:100000").Clear
End With
'ERROR BEGINS HERE
With Workbooks(WB1) ' <-- Getting Type Mismatch here
Worksheets("HORIZONTAL_DATA").Cells.Select
Selection.Copy
End With
The Workbooks object can certainly be used for finding a workbook. However, it requires either a numeric index or the workbook name itself:
Workbooks(42)
Workbooks("paxsheet.xls")
You already have the workbook you want to play with, it's in WB1, so you don't need to go looking for it.
So change:
With Workbooks(WB1) ' <-- Getting type mismatch here '
into:
With WB1 ' <-- Should not get type mismatch here '
and all should be well.
And, beyond that immediate error, since you want to use the worksheets within that workbook, you need to specify that by prefixing it with .:
With WB1
.Worksheets("HORIZONTAL_DATA").Cells.Select
Selection.Copy
End With
Further, assuming you don't need the selection to be maintained other than for that copy, you can directly copy it without first selecting:
With WB1
.Worksheets("HORIZONTAL_DATA").Cells.Copy
End With
But, of course, then it becomes pretty useless to even use the with, so you may want to just simplify the whole thing to:
WB1.Worksheets("HORIZONTAL_DATA").Cells.Copy

Moving Worksheets to Newly Created & Version Changed Workbook VBA

I am continuing working with data pulled from a mainframe. The data is largely alphanumeric, and is a continuation of building functionality onto past efforts. The loop in which the sheets are moved was created on the basis of the function discussed in this SO article.
I have consulted this SO article and independently tested the general form of such functionality, but such code is failing in this specific case, perhaps due to version issues or the way I am referencing the new workbook.
I have written a subroutine that shifts worksheets from one workbook to another. It is used in conjunction with a public variable tied to a checkbox, and is intended to provide the user with an easy way to port the form data. The public variable is used in a conditional to call the subroutine if the checkmark is in a checked state.
The code is as follows:
Public Sub MoveSheets()
' This macro moves all sheets but those noted within the If statements,(1)
' (1) which are further nested within the For Each loop.
'See http://msdn.microsoft.com/en-us/library/office/ff198017.aspx for save file format types.
'The file format of this excel macro sheet is 52: xlOpenXMLWorkbookMacroEnabled
'The default save type for the use-case is excel 2003 is compatibility mode.
'The macro is to set the current save type to one compatible with 52.
'In this case, 51: xlOpenXMLWorkbook was selected as the selected type.
'Define Excel Format storage variables.
Dim FileFormatSet As Excel.XlFileFormat
Dim OriginalFileFormatSet As Excel.XlFileFormat
Dim TempFileFormatSet As Excel.XlFileFormat
'Define worksheet/workbook variables.
Dim IndividualWorkSheet As Worksheet
Dim NewWorkBook1 As Workbook
'Set variable to store current time.
Dim CurrentTime As Date
'The original file format.
OriginalFileFormatSet = Application.DefaultSaveFormat
'The file format to be used at the end of the procedure after all is said and done.
FileFormatSet = OriginalFileFormatSet
'The currently desired file format.
TempFileFormatSet = xlOpenXMLWorkbook
'The currently desired file format set as the set default.
Application.DefaultSaveFormat = TempFileFormatSet
'Disable application alerts. Comment the line below to display alerts (2)
'(2) in order to help check for errors.
Application.DisplayAlerts = False
'Save new workbook "NewWorkBook" as default file format.
Workbooks.Add.SaveAs Filename:="NewWorkBook", FileFormat:=Application.DefaultSaveFormat
'Set variable to new workbook "NewWorkBook", which is in .xlsx format.
Set NewWorkBook1 = Workbooks("NewWorkBook.xlsx")
'Activate Macro Window.
Windows("ShifterMacro.xlsm").Activate
'For each worksheet, shift it to the workbook "NewWorkBook" if (3)
'(3) it fails outside the criteria set listed below.
For Each IndividualWorkSheet In ThisWorkbook.Worksheets
If IndividualWorkSheet.Name <> "Sheet1" And IndividualWorkSheet.Name <> "Criteria" And _
IndividualWorkSheet.Name <> "TemplateSheet" And IndividualWorkSheet.Name <> "TemplateSheet2" And _
IndividualWorkSheet.Name <> "Instructions" And IndividualWorkSheet.Name <> "Macro1" And _
IndividualWorkSheet.Name <> "DataSheet" Then
'Select each worksheet.
IndividualWorkSheet.Select
'Shift the worksheetover to the new workbook.
'****NOTE: THIS CODE CURRENTLY RESULTS IN A '1004' RUN-TIME ERROR.****
IndividualWorkSheet.Move After:=NewWorkBook1.Sheets.Count
End If
Next
'An ugly set of If Then statements to clean the new workbook (4)
'(4) of its previous sheets, assuming entries are to be made.
If NewWorkBook1.Sheets.Count > 1 Then
NewWorkBook1.Sheets("Sheet1").Delete
End If
If NewWorkBook1.Sheets.Count > 1 Then
NewWorkBook1.Sheets("Sheet2").Delete
End If
If NewWorkBook1.Sheets.Count > 1 Then
NewWorkBook1.Sheets("Sheet3").Delete
End If
'********** CODE CHECKED BUT UNTESTED WITHIN THESE BOUNDARIES **********
'Activate the Window for the new workbook if it is inactive.
Windows("NewWorkBook.xlsx").Activate
'If the number of sheets are greater than 1... (5)
If Sheets.Count > 1 Then
'(6) The time value is parsed to remove unusual characters, following (5)
'(6) the logic of this SO article: https://stackoverflow.com/questions/11364007/save-as-failed-excel-vba.
'Formatted current time as per http://www.mrexcel.com/forum/excel-questions/273280-visual-basic-applications-format-now-yyyymmddhhnnss.html
CurrentTime = Format(Now(), "yyyy-mm-dd-hh-nn-ss")
'(5) Then go ahead and save the file with the current date/time information.
NewWorkBook1.SaveAs Filename:="Form_Data_" & Now, FileFormat:=Application.DefaultSaveFormat
End If
'Set SaveChanges = True, as per https://stackoverflow.com/questions/9327613/excel-vba-copy-method-of-worksheet-fails
ActiveWorkbook.Close SaveChanges:=True
'********** END CODE BOUNDARY **********
'Activate the Window for the Macro.
Windows("ShifterMacro.xlsm").Activate
'Activate a specific sheet of the Macro.
ActiveWorkbook.Sheets("Instructions").Activate
'Change Display Alerts back to normal.
Application.DisplayAlerts = True
'Reset the view for the original data sheet.
With Sheets("Sheet1")
'For when this process is repeated.
If .FilterMode Then .ShowAllData
End With
'Return the Default save format to the original file format.
Application.DefaultSaveFormat = FileFormatSet
End Sub
The code fails at line 62, and results in a '1004' Run-Time error:
IndividualWorkSheet.Move After:=NewWorkBook1.Sheets.Count
The worksheet referenced holds the correct test value of '100-AAA'. The Sheets.Count is equal to 3. The NewWorkBook1 variable holds the value NewWorkBook.xslx. The path of the generated workbook "NewWorkBook.xslx" is the same as the macro workbook. My version of excel is 2007, although the default for my users is 2003, even though they have the capacity and the installation for 2007.
Why is this run-time error with my Move occuring, and how do I correct this error in order to get my worksheets over to the newly generated workbook?
This:
IndividualWorkSheet.Move After:=NewWorkBook1.Sheets.Count
just specifies to move the sheet within the same workbook (and it will error if NewWorkBook1 has more sheets than its parent workbook)
Maybe try:
IndividualWorkSheet.Move After:=NewWorkBook1.Sheets(NewWorkBook1.Sheets.Count)

VBA - How to copy row in Excel from one workbook to another?

Despite many posts I have looked through being of along the same lines as my question, none of the answers satisfy what I am looking for. If you can link me to one I'd gladly read it.
I have a workbook with worksheets. For simplicity, let's say my workbook has a worksheet. And in my worksheet which is called "Sheet1", there is data in cells A1 to A4.
What I want my VBA code to do is:
Copy row 1 (or specifically cells A1 to A4) of Workbook 'A' into Range variable 'myRange'
Create a new workbook, let's call this one Workbook 'B'
Give Workbook 'B's default "sheet1" a new name to "Test Name"
Open Workbook 'B' (though I realise that VBA code "Workbooks.Add" opens a new book so this step may be redundant since Workbooks.Add covers half of point 2 and 3)
Paste 'myRange' into first row of 'Workbook B'
Save 'Workbook B' with name "Test Book" and a timestamp enclosed in square brackets. The file must also be of the file extension "xls"
Close 'Workbook B' and return to 'Workbook A'
What I have so far is this:
Sub OpenAndSaveNewBook()
'Declarations
Dim MyBook As String
Dim MyRange As Range
Dim newBook As Workbook
'Get name of current wb
MyBook = ThisWorkbook.Name
Set MyRange = MyBook.Sheets("Sheet1").Range("A1,F1")
'Create/Open new wb
newBook = Workbooks.Add
'Save new wb with XLS extension
ActiveWorkbook.SaveAs Filename:=ThisWorkbook.Path & "/" & "TEST-BOOK", _
FileFormat:=xlNormal, CreateBackup:=False
'===NOTE: BEFORE THE FOLLOWING RUNS I NEED TO PERFORM ACTIONS ON CELLS VIA VBA ON
'===WORKBOOK 'A'. DOES THE NEWLY CREATE WORKBOOK BECOME THE PRIMARY/ACTIVE WORKBOOK
'===? AND SO THEN DO I NEED TO ACTIVATE WORKBOOK 'A'?
ActiveWorkbook.Close savechanges:=True
'Return focus to workbook 'a'
MyBook.Activate
End Sub
As you can see, I am lacking the code that will handle:
the pasting of my copied data to the new workbook
the changing of the new workbook's sheet1 name to something else
adding a timestamp to the filename string on save
Lastly, I have included a question in my code as I think I may have a misunderstanding of the ActiveWorkbook method. AFAIK when the code "Workbooks.Add" runs this becomes the Active Workbook, i.e. one with the focus. Does this effect how the VBA code running on Workbook 'A'? Does this mean that if I wanted to add code to manipulate cells of Workbook 'A' then I would need to use "MyBook.Activate" where 'MyBook' holds the string of Workbook 'A's actual title?
Any help will be greatly appreciated.
Thanks,
QF
Instead of copy pasting the way you mentioned above, you can directly do this. This will also negate the use of a variable.
MyBook.Sheets("Sheet1").Rows("1:4").copy _
newBook.Sheets("Sheet1").Rows("1")
EDIT
I just noticed an error with your code.
newBook = Workbooks.Add
This line will give you an error as you have to use Set
Your code can be written as
Option Explicit
Sub OpenAndSaveNewBook()
Dim MyBook As Workbook, newBook As Workbook
Dim FileNm As String
Set MyBook = ThisWorkbook
FileNm = ThisWorkbook.Path & "\" & "TEST-BOOK.xls"
Set newBook = Workbooks.Add
With newBook
MyBook.Sheets("Sheet1").Rows("1:4").Copy .Sheets("Sheet1").Rows("1")
'Save new wb with XLS extension
.SaveAs Filename:=FileNm, FileFormat:=xlNormal, CreateBackup:=False
.Close Savechanges:=False
End With
End Sub
MORE EDIT
Elaborating on the use of SET
I would recommend you to see this post.
LINK: Worksheets does not work
Avoid references to ActiveWorkbook in favour of explicit references wherever possible.
As you've found, it can be confusing knowing what's currently active, and you do not need to activate a workbook to manipulate it.
So you should be using
newBook.SaveAs...
newBook.Close...
Recorded macros tend to activate workbooks in order to work on them, but that's because that's the way a human who recorded them works! All activation really does is change focus.
The same applies to making selections and then manipulating the current selection; it's not necessary in VBA and tends to be slower than direct manipulation.
The awesome thing about Excel is the 'Record Macro' function. I started recording a macro and just followed the steps you outlined, then made a few minor modifications to the code that Excel provided as the recorded macro:
Range("A1:F1").Select
Selection.Copy
Workbooks.Add
ActiveSheet.Paste
Sheets("Sheet1").Name = "Test Name"
Application.CutCopyMode = False
myNewFileName = myPath & myTestName & "_" & Date & ".xls"
ActiveWorkbook.SaveAs Filename:=myNewFileName _
, FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
The Date function returns the current system date. It is important to note that the square brackets that you wanted are not valid filename characters; Excel will throw an error if you try to use those.
Turn the macro-recorders on; carefully execute the steps you want; stop the recorder; "edit" the macro generated. Fix as you need to make the program you intend, e.g., to parameterize it.