Cut/paste with from one workbook to another - excel

I have a workbook called "Data" with raw data on the "Unprocessed" sheet.
I am trying to create a sheet for every agent, called "agent" (this will be changed for every agent but for ease we will call it this for now) that pulls raw data, one row at a time, into their work area from the data workbook.
I need cells A2:M2 cut from the "Unprocessed" sheet and pasted into A4:M4 of the "agent" sheet.
I get "out of range" error. I tie this sub to a button the agents hit to bring up a new row of data.
Sub newcancel_click()
If Range("M4").Value = "EN" Then
MsgBox "You must Complete Previous cancellation.", vbCritical, "Error"
Else
Sheets("Uncompleted").Select
Range("A1:L1").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Jeremy").Select
Range("B4").Select
ActiveSheet.Paste
Sheets("Uncompleted").Select
Rows("1:1").Select
Application.CutCopyMode = False
Selection.Delete
Shift:=xlUp
Sheets("Jeremy").Select
End If
End Sub
After this, I will need to create a sub to move the data from the work area to a "Processed" sheet on the "Data" book. I am comfortable that I will be able to write this sub once I get the first one working.

As for your current code, the following should work better.
Sub Newcancel_click2()
If ThisWorkbook.Sheets(1).Range("M4").Value = "EN" Then
MsgBox "You must Complete Previous cancellation.", vbCritical, "Error"
Else
Sheets("Jeremy").Range("B4:M4").Value = Sheets("Uncompleted").Range("A1:L1").Value
Sheets("Uncompleted").Rows(1).EntireRow.Delete shift:=xlUp
End If
End Sub
An interesting read for you: How to avoid using select in VBA
As for your issue, "Subscript out of range" might mean some of your ranges aren't defined properly. Your selection might not match the copy destination, or (most likely) the sheet you're referring to doesn't exist (either a typo or you've not created it yet).
To refer to another workbook you can use Workbooks("Workbook name").Sheets("Sheet name").Range etc. You can use activeworkbook to refer to the currently active workbook (not recommended as per above link to avoid using select) and you can refer to the workbook your VBA code is in with Thisworkbook, this is easier than using two statements: Workbook("Name for this one") and Workbook("Name for the other one")
In your case this would look something like:
Sub Newcancel_click2()
If ThisWorkbook.Sheets(1).Range("M4").Value = "EN" Then
MsgBox "You must Complete Previous cancellation.", vbCritical, "Error"
Else
Workbook("Agent").Sheets("Jeremy").Range("B4:M4").Value = Thisworkbook.Sheets("Uncompleted").Range("A1:L1").Value
Thisworkbook.Sheets("Uncompleted").Rows(1).EntireRow.Delete shift:=xlUp
End If
End Sub
(please note I made an approximation to most of your workbook and sheet names, please check and replace with your actual names)

Related

Run-time error '1004': Microsoft Excel cannot paste the data

I have looked up the question and have seen several solutions addressing things like Select or having protected worksheets, none of which apply to me here.
For various reasons, I can't post the entire code, but I will give a description of what it does and post the exact sub that is giving me issues.
I have a Macro that generates a number of worksheets based on the Month and Year input by the user (so "1" - "31" or "1" - "30" etc). To generate these worksheets, the macro makes copies of a worksheet fittingly named "EXAMPLE". One thing that is copied is a picture (just a rectangle with the word 'Export' on it) that has a macro attached to it.
I recently made what I thought was a cosmetic change by moving the location of this picture, since then, when I run the macro I get an error:
"Run-time error '1004':
Microsoft Excel cannot paste the data."
And options for 'End' 'Debug' and 'Help'
If I select 'Debug' it points me to a second macro which is called during the process of the generation macro'
Sub CopyAllShapes()
Dim ws As Worksheet
' Sets the non-generated worksheets as an array
nSheets = Array("EXAMPLE", "Weekly Totals", "Menu")
' Copies the Picture from the EXAMPLE sheet to all worksheets not in the array and then assigns a
' seperate Macro called "Export" to the picture on each of these sheets.
For Each ws In ActiveWorkbook.Worksheets
If Not IsNumeric(Application.Match(ws.Name, nSheets,0)) Then
Sheets("EXAMPLE").Shapes("Picture 1").Copy
ws.Range("J62").PasteSpecial
ws.Shapes("Picture 1").OnAction = "Export"
End If
Next ws
Application.CutCopyMode = xlCopy
End Sub
The Debug option highlights the line
ws.Range("J62").PasteSpecial
What really confuses me is that if I select 'End' instead of 'Debug', the macro stops, but all the the sheets have had the picture pasted as well as the Export Macro assigned and everything works as expected. If I were the only person using this, it would be a minor annoyance, but this document is used by many people that can't reliable be told to "just ignore" the error. Since the macro is functioning as expected, how can i troubleshoot what is causing the problem and make the error go away?
As I said, I can't post the entire macro, but I can post some bits and pieces if anyone needs more info.
Not a pure fix, but this code will retry the Copy/Paste if it fails (up to 3 times), instead of just dropping it:
Const MaxRetries AS Long = 3
Sub CopyAllShapes()
Dim ws As Worksheet
Dim TimesRetried As Long
' Sets the non-generated worksheets as an array
nSheets = Array("EXAMPLE", "Weekly Totals", "Menu")
' Copies the Picture from the EXAMPLE sheet to all worksheets not in the array and then assigns a
' seperate Macro called "Export" to the picture on each of these sheets.
For Each ws In ActiveWorkbook.Worksheets
If Not IsNumeric(Application.Match(ws.Name, nSheets,0)) Then
TimesRetried = 0
CopyExampleShape:
On Error Resume Next
Sheets("EXAMPLE").Shapes("Picture 1").Copy
ws.Range("J62").PasteSpecial
'If the Copy/Paste fails, retry
If Err Then
On Error GoTo -1 'Clear the Error
'Don't get stuck in an infinite loop
If TimesRetried < MaxRetries Then
'Retry the Copy/paste
TimesRetried = TimesRetried + 1
DoEvents
GoTo CopyExampleShape
End If
End If
On Error GoTo 0
ws.Shapes("Picture 1").OnAction = "Export"
End If
Next ws
Application.CutCopyMode = xlCopy
End Sub
I have come across a similar issue before, and it was been down to another program (in one case Skype) reacting to data being added to the Clipboard by "inspecting" it. That then briefly locked the clipboard, so the Paste/PasteSpecial operation failed. This then caused the Clipboard to be wiped clean... All without Excel doing anything wrong.
"It is possible to commit no mistakes and still lose. That is not a weakness; that is life." ~ Jean-Luc Picard
On moving to Office 365 and Win10 (can't say which of those was the culprit) I found a bunch of existing macros which would give that same error when trying to paste a copied image onto a worksheet.
When entering debug, the "paste" line would be highlighted, but if I hit "Continue" it would (after one or two attempts) run with no errors.
I ended up doing this:
'paste problem fix
Sub PastePicRetry(rng As Range)
Dim i As Long
Do While i < 20
On Error Resume Next
rng.PasteSpecial
If Err.Number <> 0 Then
Debug.Print "Paste failed", i
DoEvents
i = i + 1
Else
Exit Do
End If
On Error GoTo 0
i = i + 1
Loop
End Sub
...which looks like overkill but was the only reliable fix for the problem.
EDIT: cleaned up and refactored into a standalone sub.
Just wanted to let everyone know I have found a (sort of) solution. Based on the answers/comments from Tim Williams and PeterT I modified the code to look like this:
Sub CopyAllShapes()
Dim ws As Worksheet
' Sets the non-generated worksheets as an array
nSheets = Array("EXAMPLE", "Weekly Totals", "Menu")
' Copies the Picture from the EXAMPLE sheet to all worksheets not in the array and then assigns a
' seperate Macro called "Export" to the picture on each of these sheets.
For Each ws In ActiveWorkbook.Worksheets
If Not IsNumeric(Application.Match(ws.Name, nSheets,0)) Then
Sheets("EXAMPLE").Shapes("Picture 1").Copy
On Error Resume Next
ws.Range("J62").PasteSpecial
On Error Goto 0
ws.Shapes("Picture 1").OnAction = "Export"
End If
Next ws
Application.CutCopyMode = xlCopy
End Sub
This has successfully ignored the error and everything is working properly now! Thanks everyone for your help, hopefully this aids someone else in the future!

Excel VBA Sub breaking after .UsedRange.Delete

I have an excel project where I have tables in sheets (a basic database). The aim is to track the progress of pupils regarding different objectives they have to fulfill in different matters (and sub, sub-sub and sub-sub-sub-matters). I am trying to make a UserForm for the teacher to select a specific pupil, matter, sub...sub-mater set and get the level achieved in the objectives corrsponding to that specific set. I am at the stage of selecting a set of parameters :
UserForm, not finished
My problem is : in the case I select a matter, then a sub-matter, and then come back to change the main matter, Excel is doing something super weird. It stops a Sub after a specific line and .Activate does not work anymore for selecting a sheet in other Subs:
Sub ListMatieres_Change()
If Not IsNull(ListMatieres.Column(0)) Then
With Worksheets("S-matiere_tmp")
.Activate
.UsedRange.Delete 'Stops after this line------------------------------------------------
getRows("S-matiere", "s_matiere", "Parent", ListMatieres.Column(0)).Copy
.Activate
Range("A1").PasteSpecial Paste:=xlPasteValues
ListSmatieres.RowSource = .UsedRange.Address
End With
Sheets("Accueil").Activate
End If
ListSsmatieres.RowSource = ""
ListSssmatieres.RowSource = ""
End Sub
Sub ListSmatieres_Change()
If Not IsNull(ListSmatieres.Column(0)) Then
With Sheets("SS-matiere_tmp")
.Activate
.UsedRange.Delete 'Getting an error here, because the .activate has not worked----------
getRows("SS-matiere", "ss_matiere", "Parent", ListSmatieres.Column(0)).Copy
.Activate
Range("A1").PasteSpecial Paste:=xlPasteValues
ListSsmatieres.RowSource = .UsedRange.Address
End With
Sheets("Accueil").Activate
End If
ListSssmatieres.RowSource = ""
End Sub
Changing the matter triggers the first Sub, which triggers the second.
Here is a link for the .xlsm file : Drive link
I am really clueless, because the error given by Excel is only a consequence of some unexpected behavior I cannot explain...
Any help is welcome !

Excel VBA - random runtime errors

I’m very new to Excel VBA but managed to create three buttons in a staff timesheet. All buttons work as needed, however, one particular button is causing random issues – about 90% of the time it works, but from time to time it will crash Excel or give an error such as runtime error '-2147417848 (800 10 108)': Automation error The object invoked has disconnected from its clients. Other times it’s a similar message, saying Method ‘Insert’ of object ‘Range’ failed.
It’s happening in different versions of Excel on different computers. The task is not complex but I’m stumbling with my VBA knowledge.
The user clicks the button to set up each formatted row in the sheet called “Timesheet”, i.e. clicking the button in “Timesheet” copies a row from sheet4 (formatted and containing formulae) and inserts it into the “Timesheet” above the button.
I’d be very grateful if someone could suggest alternative code that won’t crash Excel - many thanks in advance!
Sub NewSlot()
' NewSlot Macro used in Timesheet
'
'turn protection off
Worksheets("Sheet4").Unprotect Password:="mypasswd"
Worksheets("Timesheet").Unprotect Password:=" mypasswd "
' select row 8 in sheet4
Sheets("Sheet4").Select
Rows("8").Select
Selection.Copy
' go back to timesheet
Sheets("Timesheet").Select
' insert copied row
Dim r As Range
Set r = ActiveSheet.Buttons(Application.Caller).TopLeftCell
Range(Cells(r.Row, r.Column), Cells(r.Row, r.Column)).Offset(0, 0).Select
Selection.Insert shift:=xlDown
Application.CutCopyMode = False
'turn protection on
Worksheets("Sheet4").Protect Password:=" mypasswd "
Worksheets("Timesheet").Protect Password:=" mypasswd"
End Sub
If you are going to use VBA to repeatedly modify a protected worksheet, unprotect it then protect it once with UserInterfaceOnly:=True.
sub protectOnce()
worksheets("Timesheet").unprotect password:="mypasswd"
worksheets("sheet4").unprotect password:="mypasswd"
worksheets("Timesheet").protect password:="mypasswd", UserInterfaceOnly:=True
worksheets("sheet4").protect password:="mypasswd", UserInterfaceOnly:=True
end sub
After that has been done once you will not have to unprotect to modify with VBA. If you have to unprotect it for another reason, reprotect it with with UserInterfaceOnly:=True.
This cuts your NewSlot code down significantly. It is considered 'best practise' to avoid using Select and Activate, particularly across worksheets.
Sub NewSlot()
' select row 8 in sheet4
workSheets("Sheet4").Rows("8").Copy
' go back to timesheet
with workSheets("Timesheet")
' insert copied row
Dim r As Range
Set r = .Buttons(Application.Caller).TopLeftCell
.Cells(r.Row, "A").entirerow.Insert shift:=xlDown
end with
End Sub

Overwrite data without asking

I want to edit this macro to overwrite previous data in another workbook without prompting. See attached code. Any help would be greatly appreciated.
Sub AV()
Workbooks.Open Filename:="T:\Cleveland\Avon\Monthly Sales\Monthly Sales 2018.xls"
Windows("Sales_By_Day_Location Analysis.xlsm").Activate
Sheets("AV").Select
Range("A1:AC88").Copy
Windows("Monthly Sales 2018.xls").Activate
Sheets("Avon").Select
Range("A1:D1").PasteSpecial Paste:=xlPasteValuesAndNumberFormats
Application.CutCopyMode = False 'esp
End Sub
As per comments from John, and after tidying up your code a little, I believe something like the code below would do what you are expecting:
Sub AV()
Application.DisplayAlerts = False
Workbooks.Open Filename:="T:\Cleveland\Avon\Monthly Sales\Monthly Sales 2018.xls"
Workbook("Sales_By_Day_Location Analysis.xlsm").Worksheets("AV").Range("A1:AC88").Copy
Workbook("Monthly Sales 2018.xls").Sheets("Avon").Range("A1").PasteSpecial Paste:=xlPasteValuesAndNumberFormats
Application.CutCopyMode = False 'esp
Application.DisplayAlerts = True
End Sub
You should attempt not to use Activate or Select statements. Also your copy range is a lot bigger than your paste range, so for the purpose of this answer I've changed the paste range to A1.
If you want to then save the workbooks and close it without a prompt, you could do something like:
Workbook("Monthly Sales 2018.xls").Close SaveChanges:=True

How can I produce a regular Excel formula as the result of a query?

I have a large and complicated Excel query, which works as desired.
However, I'm implementing some real-time data-validation features (i.e. not requiring a data refresh), and I need to have a regular excel formula in one of the columns of my query results.
This formula would perform a real-time data comparison using other sheets in the workbook, intentionally independent from the query itself.
Can I add a custom column with no value?
I assume the values null or "" would overwrite any pre-existing data, so I couldn't just enter the excel formula into the results table after running the query (the formula wouldn't persist between refreshes).
For testing, I tried adding a custom column with the value "=5+2", just to see how it would behave.
let
Source = Excel.CurrentWorkbook(){[Name="tblInvoicesCategorized"]}[Content],
/* ... perform numerous query actions ... */
// Use "=5+2" as a test formula
#"Added Custom13" = Table.AddColumn(#"Added Custom12", "Stale Data", each "=5+2"),
/* ... perform numerous query actions ... */
in
#"Changed Type"
The query did output the formula as the value of the cells in the column, but Excel did not automatically execute the formulas.
I still had to manually place the cursor into a cell and press enter, to get it to execute the formula.
Manual entry of the formula, or even manual execution of a macro, is undesirable for this workbook.
Is there a way for me to have a regular formula in this query column, and have it automatically persist between data refreshes?
#"Added Custom13" = Table.AddColumn(#"Added Custom12", "Stale Data", each "=5+2"),
This is not working the way you expect it because you are returning a string literal: "=5+2"
The = is implied and quotes are not necessary
#"Added Custom13" = Table.AddColumn(#"Added Custom12", "Stale Data", each 5+2),
This will return 7 without requiring manual refresh. However, you are limited to Power Query Formulas which have a different set of functions than the standard excel formulas.
https://msdn.microsoft.com/library/1ed840b1-7e20-4419-ad2f-d82054c9b2ab
This can make accessing data from your worksheet a chore, but it is possible. Some tips can be found here:
How can I reference a cell's value in a Power Query
You cannot output a column which will directly call Excel formulas. You can use a different column in the worksheet that will call the Excel formula on the and reference a cell from the table that Power Query outputs. This cell will refresh when the Power Query table is refreshed.
a workaround is to trigger the refreshall on cell change by some VBA code ...
this was my case, hope it helps...
Private Sub Worksheet_Change(ByVal Target As Range)
'
' Dim lTest As Long, cn As WorkbookConnection
' On Error Resume Next
' For Each cn In ThisWorkbook.Connections
' lTest = InStr(1, cn.OLEDBConnection.Connection, "Provider=Microsoft.Mashup.OleDb.1", vbTextCompare)
' If Err.Number <> 0 Then
' Err.Clear
' Exit For
' End If
' If lTest > 0 Then cn.Refresh
' Next cn
If Intersect(Target, Me.Range("datachange")) Is Nothing Then Exit Sub
Application.EnableEvents = False 'to prevent endless loop
'Application.Goto Reference:="Tum_Santiyelerin_Satinalinan_Malzemeleri"
Range("Tum_Santiyelerin_Satinalinan_Malzemeleri").ListObject.QueryTable.Refresh BackgroundQuery:=False
'Application.Goto Reference:="Filtre"
'Range("Filtre").ListObject.QueryTable.Refresh BackgroundQuery:=False
'Application.Goto Reference:="Filtre_Malzeme"
Range("Filtre_Malzeme").ListObject.QueryTable.Refresh BackgroundQuery:=False
'Application.Goto Reference:="Filtre_Proje"
Range("Filtre_Proje").ListObject.QueryTable.Refresh BackgroundQuery:=False
'Application.Goto Reference:="Filtre_Firma"
Range("Filtre_Firma").ListObject.QueryTable.Refresh BackgroundQuery:=False
Application.Goto Reference:="Tum_Santiyelerin_Satinalinan_Malzemeleri"
ActiveWorkbook.RefreshAll
Application.EnableEvents = True
I realize this is an old thread, but wanted to give my answer in-case anyone else comes across it like I did. I came across this solution by accident, so I cannot say if it is by design or a bug that will be resolved with some future release.
Rather than trying to include the formula in the Query results, if you add a column with your formula directly to the end of the output table and choose the option "Overwrite all cells in this column with this formula," then when you refresh your query the formula will populate for all rows of the table and will resolve like a normal worksheet formula.
I know the post is a little old but I had the same problem and couldn't find a solution for it.
You can actually do this with a little trick with a macro. I have a power query with 18 different queries and some need a formula. For performance boost I wrote a little vba to refresh everything faster and save the document after the refresh. It looks like this:
Sub Aktualisieren()
Application.Calculation = xlCalculationManual
ActiveWorkbook.RefreshAll
Application.Calculation = xlAutomatic
On Error GoTo ErrorHandler
ActiveWorkbook.Save
Exit Sub
ErrorHandler: MsgBox "You can't save the file right now! This isn't a bug!", vbInformation Exit Sub
End Sub
Now to my problem I got some formulas in my query like this on
Query with formula
If you add the following code to my Sub Aktualisieren(), the formula will be automatically activated:
Sub Aktualisieren()
Application.Calculation = xlCalculationManual
ActiveWorkbook.RefreshAll
ThisWorkbook.Sheets("Report").Range("AM2").Select
ActiveCell.FormulaR1C1 = _
"=IFERROR(VLOOKUP([#Arbeitsplatz],Verzeichnis!R3C5:R26C6,2,FALSE),"""")"
ThisWorkbook.Sheets("Report").Range("AM2").Select
Selection.AutoFill Destination:=Range("Report[Prio Anlage]")
Application.Calculation = xlAutomatic
On Error GoTo ErrorHandler
ActiveWorkbook.Save
Exit Sub
ErrorHandler: MsgBox "You can't save the file right now! This isn't a bug!", vbInformation
Exit Sub
End Sub
I did it with the Macro maker built within Excel. But basically you can copy that code and only need to change ThisWorkbook.Sheets("Report").Range("AM2").Select, your formula "=IFERROR(VLOOKUP([#Arbeitsplatz],Verzeichnis!R3C5:R26C6,2,FALSE),"""")" and the Autofill Destination.
I hope it can help you.

Resources