Saving/restoring clipboard in Excel VBA - vba

I have an Excel workbook with many sheets. Most sheets have some code in the Worksheet_Activate() subroutine.For some reason this code causes the contents of the clipboard to be lost - extremely annoying, as spreadsheet user cannot copy and paste between sheets.
In an attempt to fix this I have added the following lines at the beginning of the Worksheet_Activate code:
Dim dClipBoard As MsForms.DataObject
On Error Resume Next
Set dClipBoard = New MsForms.DataObject
dClipBoard.GetFromClipboard
And the following lines just before exit of the Worksheet_Activate code:
On Error Resume Next
dClipBoard.PutInClipboard
Unfortunately, it doesn't work. My clipboard is still lost when I move from sheet to sheet.

I can imagine 2 different workarounds for this case.
1- If possible change the code in the worksheets. Where ever the .copy command is used replace it with codes like these:
range("Some Range") = range("Some other range")
2- If changing the code is not possible (using the approach you are currently using) instead of storing the data to an MsForms.DataObject you could copy them to some auxiliary sheet, And retrieve the data from the worksheet before the exit worksheet event triggers.

Related

Unable to paste into a protected worksheet using VBA, but can do it manually

I have written a macro that should copy a range of data from one workbook into another. The sheet in the other workbook is password protected, but if I copy and past manually, it allows me to do so. However, when I try and write this into my macro, it won't allow the paste.
Code is currently as follows:
Sub COPYT()
'
' COPYT Macro
Range("B2:U109").Select
Selection.Copy
Workbooks.Open Filename:= _
"_FileName_.xls"
Windows("_FileName_.xls").Activate
Range("H10").Paste
End Sub
When I run the macro as is, I get a
Run-time error '438': "Object doesn't support this property or method"
and the debugger shows that the issue is with the last line Range("H10").Paste
I can't unprotect the sheet (compliance), and I can obviously get round this by just running the macro and then CTRL+V but (as this allows me to paste....), but I would rather that this was automated. Do I need a different syntax for the paste command due to the sheet being protected?
Thanks
Paste is a method of the worksheet, not range. Try this. I have assumed sheet references but you may need to adjust.
Sub COPYT()
Dim wb As Workbook
Set wb = Workbooks.Open(Filename:="_FileName_.xls")
wb.Sheets("compliance").unprotect
ThisWorkbook.Sheets(1).Range("B2:U109").Copy wb.Sheets("compliance").Range("H10")
wb.Sheets("compliance").protect
End Sub

Removing links from copied worksheet

What I want to do
I want a code in my workbook (wbDestination) that opens another workbook (wbBosOriginal) and copies an entire sheet as values (wbBosOriginal has a lot of code in it, in modules and in the worksheet in question, and I do not want this code because it references stuff in wbB that doesn't exist in wbDestination). I have had great problems pasting as values, because it will not paste columns and rows that are currently hidden. So this is why I decided to import the whole sheet instead.
What I tried and what's wrong with it
Here is a block of code I used to copy the worksheet in the destination workbook, in the last index position. The problem with it is that some links still exist to the old workbook (Formulas, validation lists, conditionnal formatting). I have deleted all these links but STILL when I paste the sheet successfully, save and reopen, I have an error saying some content is unreadable. I believe there are still some elements linked to the old workbook.
Set wbBosOriginal = Workbooks.Open(strChosenPath, ReadOnly:=True)
With wbBosOriginal.Sheets("BOS")
.Visible = True
'Pastes the ws in last position in wbDestination
.Copy after:=wbDestination.Sheets(wbDestination.Worksheets.Count)
Set wsNewBos = Worksheets(Worksheets.Count)
'Deletes VBA code in the copied sheet
ThisWorkbook.VBProject.VBComponents.Item(wsNewBos.CodeName).CodeModule.DeleteLines 1, _
ThisWorkbook.VBProject.VBComponents.Item(wsNewBos.CodeName).CodeModule.CountOfLines
End With
The worksheet is successfully pasted with no code in it, with everything else it had previously. I then remove all formulas, conditionnal formatting, and validation lists. Even after removing those as well, I still get an error when opening the workbook.
My question
Apart from conditional formatting, validation lists, VBA code, and formulas linking a worksheet that was pasted to a new workbook, what other elements could cause the workbook from opening in repair mode every time due to existing links to the old workbook?
If my question is not clear, comment and I will clarify.
Dealing directly with VBE seems a bit heavy-handed to me. If your code is manipulating several workbooks, I would put the code in an add-in and not have it in any workbook. (Technically *.xlam addins are workbooks, but when I say "workbook" I mean normal *.xls, *.xlsx, *.xlsm, etc.)
That said, if you're just copying cell values (which may be formulas) between different workbooks, you shouldn't have any dependencies other than cell references, named ranges, and user-defined functions in the original workbook. I would make sure there are none of those. Please also share how you are ensuring your formulas do not have broken references.
If the issue you are having is caused by trying to avoid hidden columns and rows not allowing pastevalues, why not unhide the rows and columns and then copy only the values to the new book?
Just cycle through each of the sheets in the original book and use the method .UsedRange.Hidden = False. As far as I am aware, this should unhide every cell on the sheet and allow you to do the original pastevalues calls
This works fast and smooth (it's harder to delete ALL the data Imo):
Sub tests()
Dim AllRange As Range: Set AllRange = ActiveSheet.UsedRange
Dim ItemRange As Range
Dim myWbDestination As Workbook: Set myWbDestination = ThisWorkbook
Dim SheetDestination As String: SheetDestination = ("Sheet2")
For Each ItemRange In AllRange
With myWbDestination.Sheets(SheetDestination)
.Range(ItemRange.Address) = ItemRange.Value
End With
Next ItemRange
End Sub
Repair mode can be triggered by many factors, you would need to post the code you are getting to look for an explanation, it would be like asking why vba may broke

Excel VBA copy Run-Time error '1004'

I can't figure out what's wrong with my VBA:
Private Sub CommandButton4_Click()
Sheets("Opgave").Select
Range("F9:G14").Select
Selection.Copy
Sheets("Reserve").Select
Range("E3").Select
End Sub
Excel says Range("F9:G14").Select is wrong!
You need to Activate the sheet, because Range is implicitly referring to the active worksheet, and you're wrongly assuming Selecting something will necessarily Activate it.
I've executed your code with "Sheet1" and "Sheet2" without any error being thrown, "Sheet1!F9:G14" selected for copy and "Sheet2!E3" selected, which seems to be what this code wants to achieve.
Still, I'd like to say...
Avoid problems, avoid Select and Activate in VBA code.
Sheets have a CodeName property that you can change from, say, Sheet1 to OpgaveSheet, or Sheet2 to ReserveSheet. Then this code is valid:
OpgaveSheet.Range("F9:G14").Copy ReserveSheet.Range("E3")
The Name of a worksheet is the text that's displayed in the tab for it in Excel. You can also use that to get a reference to a worksheet:
Dim opgaveSheet As Worksheet
Set opgaveSheet = ThisWorkbook.Worksheets("Opgave")
Dim reserveSheet As Worksheet
Set reserveSheet = ThisWorkbook.Worksheets("Reserve")
And when you want to work with a specific range, keep a reference to it instead of Selecting it and working with the Selection:
Dim source As Range
Set source = opgaveSheet.Range("F9:G14")
Dim destination As Range
Set destination = reserveSheet.Range("E3")
source.Copy destination
Code that doesn't constantly interact with worksheets (via Select and Activate) is going to perform better, will be easier to follow, debug and maintain, and will be much less error-prone.

Excel VBA - Can I manipulate data on another workbook?

Background:
Every month I need to run a report. However, before I can do this, I must export some data in to excel. Once the data is in excel, I have to alter some columns and get the format correct before it is appended to the end of another document to do some analysis on.
What I would like:
I would like to have the document that I append the data to open. I will then export the data in to excel from my program (excel just opens with the data and it is not saved anywhere) and from my larger document, run a VBA script that will alter the data on the other workbook (Book1) so that it can be copied over to the analysis document when in the correct format.
What I have so far:
I have started basic. So far all I am trying to do is set all the cells to the correct height to make it easier to read. However, when I run this code, I get:
Run-time error '9':
Subscript out of range
The code I have so far is:
Sub Data_Ready_For_Transfer()
' Format all cell heights to 15
With Workbooks("Book1.xlsm").Worksheets("Sheet1")
Cells.RowHeight = 15
End With
End Sub
It appears to be having issues with the With Workbooks("Book1.xlsm").Worksheets("Sheet1") part of the code. I have also tried With Workbooks("Book1").Worksheets("Sheet1") and I have tried this with the open, unsaved document and a saved version of the workbook.
Am I missing something obvious?
As follow up from comments, workbook Book1 was opened in another instance of Application object.
In that case this code should work (for already opened workbook):
Sub Data_Ready_For_Transfer()
Dim wb As Workbook
Set wb = GetObject("Book1")
'if we get workbook instance then
If Not wb Is Nothing Then
With wb.Worksheets("Sheet1")
.Cells.RowHeight = 15
End With
End If
End Sub
One more issue, I've changed Cells.RowHeight = 15 to .Cells.RowHeight = 15 to specify, that Cells belongs to workbook Book1 sheet Sheet1.

Excel 2010 VBA running in all opened files

I have one excel file (*.xlsm) with VBA code on first sheet:
Private Sub Worksheet_Calculate()
ActiveSheet.ChartObjects("Podtlak").Chart.Axes(xlCategory, xlPrimary).MaximumScale = Range("AV79").Value
End Sub
And second excel file with macro that is changing value in cell in first excel (it is automaticaly recalculated) and then copy value of new result from first excel and paste it to second excel file.
Problem is: when macro is going to second excel and paste value, worksheet is recalculated and code from first excel is calling, but it stops with error because in second excel it cant find chart object "Podtlak".
How to set worksheet_calculate() to run only for file whitch one is it written?
Try specifying the workbook:
ThisWorkbook.ActiveSheet.ChartObjects("Podtlak").Chart.Axes(xlCategory, xlPrimary).MaximumScale = Range("AV79").Value
Or specifying the worksheet and workbook:
ThisWorkbook.Worksheets("yourWorksheetName").ChartObjects("Podtlak").Chart.Axes(xlCategory, xlPrimary).MaximumScale = Range("AV79").Value
I like the 2nd option best as you are clearly specifying the worksheet and workbook that this function runs on. Anytime you use ActiveSheet or ActiveWorkbook, you are relying on the fact that your intended worksheet is active when the code runs.