I am trying to write a basic script to open another file, refresh the data in that file, save that updated file off as values (not formulae), and then closes the originally opened file containing the formulas without saving. My issue is that the file doesn't actually pull the requested formulae until after the macro has finished and the 'updated' file has saved itself away. In other words the formulae start to refresh, apparently never finish refreshing, and then copy/paste over themselves with the "#N/A Requesting Data..." string, instead of the actual data. I've seen a number of simlar questions around about this, but I haven't seen one which defines why the issue exists in the first place. I have tried runnign the refresh and the saving in different subs, and have tried a number of different methos of waiting for the formulae to finish refreshing, without avail. E.g.:
'ATTEMPT 1
'Application.Calculate
'If Not Application.CalculationState = xlDone Then
' DoEvents
'End If
'ATTEMPT 2
'Do: DoEvents: Loop While Application.CalculationState = xlCalculating
'ATTEMPT 3
'Do Until ActiveSheet.CalculationState = xlDone
' DoEvents
'Loop
Here is the code which runs once the initiating file is openend:
Sub Auto_Open()
Call Refresh
'COPY PASTE VALUES
ActiveSheet.Cells.Copy
'COPY UPDATED SHEET TO NEW BOOK & SAVE AS .XLS
Workbooks.Add
With ActiveSheet
.Cells.PasteSpecial xlValues
.Cells.PasteSpecial xlFormats
End With
Application.CutCopyMode = False
ActiveWorkbook.SaveAs (NewBook & Format(Now(), "DD-MMM-YYYY hh mm AMPM") & ".xls")
End Sub
Here is the sub which actually refreshes the data:
Sub Refresh()
Application.Calculation = xlCalculationManual 'ENSURE IT ONLY PULLS DATA WHEN YOU TELL IT TO
Dim wkbook As Workbook
Dim OpenedBook As String
OpenedBook = "G:\Folder Name\Sub Folder\File Opened in Folder.xlsx" 'FULL PATH OF WORKBOOK TO BE OPENED
NewBook = "G:\Folder Name\Sub Folder\File Saved in Folder\" 'BASE NAME OF THE SAVED WORKBOOK
'OPEN THE DESIRED WORKBOOK
Set wkbook = Workbooks.Open(OpenedBook)
wkbook.Activate
'REFRESH ALL BBG FORMULAE
Application.Run "RefreshAllWorkbooks"
Application.Run "RefreshAllStaticData"
Application.Wait (Now + TimeValue("00:00:10"))
End Sub
The actual formula being refreshed work otherwise, and are straighforward BBG BDH formulae. E.g. =BDP(B3&" curncy", "px_mid") where B3 has a currency pair like "EURUSD". Any thoughts on why the formulae are not pulling, even after the Wait and DoEvents 'fixes'? I have a feleing I am misunderstanding something fundamental about how BBG/VBA works, so please help me understand why this situation exists in the first place. Thanks in advance!
Related
I am working on creating a macro to simplify things that I do on a daily basis. The idea behind this macro is to copy 7 worksheets from the parent report, open a new workbook, paste and hardcode the data, save it to my desktop and close the new workbook.
As I am working through debugging and testing my code I am running into a problem which I do not understand why it is happening. If I boot up windows and run the macro the first time in my excel workbook, I get no issues the first time I run it for the 7 reports. The problem comes up when I try to add code or fix issues and run the code again. I keep getting " Run-time error '1004' Application-defined or object defined error".
I am trying to debug and when I hit F8 for debugging and stepping into the code, it seems it gets hung up around step #4 when it is trying to close when I run it more than once. I am learning and using Leila Gharani's course, but I don't think I got this far in the course yet to understand. If someone can please help me so I can understand this concept, I would greatly appreciate it.
Thank you
'1. Select Parent Report and select BD Tab
Workbooks("Parent Report").Activate
Worksheets("BD").Select
'2. Select all cells from BD tab, open new workbook , paste data, and hardcode it.
Cells.Select
Cells.Copy
Workbooks.Add
Range("A1").PasteSpecial xlPasteAll
Cells.Select
Cells.Copy
Range("A1").PasteSpecial xlPasteValues
Cells.EntireRow.AutoFit
'3. Rename worksheet to BD and cell "A2" to BD.
ActiveWorkbook.ActiveSheet.Name = "BD"
Range("A2").Value = "BD"
Range("A1").Select
'4. Save current flash report to local drive, with monthly naming format and close it.
ActiveWorkbook.SaveAs "C:\Users\mylocaldriveinfo\Desktop\Flash Reports" & "\BD Monthly Reporting - Preliminary " & Format(Date, "mmm") & " " & Format(Date, "yyyy")
ActiveWorkbook.Close
I just figured it out. It was my one drive at work giving me an issue. I disabled it, as I never use it and doing so I have not been able to replicate the error.
I am sure this code isn't best practice, but it works for now.
Option Explicit
Sub CopySheets()
Const FOLDER = "C:\Users\mylocaldriveinfo\Desktop\Flash Reports\BD Monthly Reporting -"
Dim wbNew As Workbook, wbMaster As Workbook, sht, n As Long
Set wbMaster = ThisWorkbook
' create new workbook
Set wbNew = Workbooks.Add(1) ' 1 sheet
n = 1
For Each sht In Array("BD", "Sheet2", "Sheet3", "Sheet4", _
"Sheet5", "Sheet6", "SHeet7") ' 7 sheet names
wbMaster.Sheets(sht).Copy After:=wbNew.Sheets(n)
n = n + 1
With wbNew.Sheets(n)
.UsedRange.Value = .UsedRange.Value
.Range("A2") = sht
End With
Next
With wbNew
' delete blank sheet
Application.DisplayAlerts = False
.Sheets(1).Delete
Application.DisplayAlerts = True
' save
.SaveAs Filename:=FOLDER & Format(Date, "mmm yyyy")
.Close
End With
MsgBox "Done", vbInformation
End Sub
I wrote several macros for workbook and I have noticed that all the macros run but then at the last action, Excel crashes.
After much troubleshooting, I found the trigger: "Activesheet.move" or "Activesheet.delete." It seems whenever a sheet is deleted from a workbook (or moved to a new workbook), Excel crashes.
Below is the final macro which triggers Excel to crash. The workbook (Template.xlsm) has 3 other sheets so deleting one should not prompt it to close. Essentially, I press the "FinishButton" which is assigned the SaveTemplate() macro. The Macro makes sure there is data in D8 before continuing. It then deletes the "FinishButton" before deleting the activesheet.
Can someone please advise what I am doing wrong or what is causing the crash?
Sub SaveTemplate()
Dim dtToday As String
Dim workdoc As String
dtToday = Format(Date, "mm_dd_yyyy")
workdoc = "Working_Doc_" & dtToday
Workbooks("Template.xlsm").Activate
If Sheets(workdoc).Range("D8").Value = "" Then Exit Sub
Sheets(workdoc).Unprotect Password:="password"
Sheets(workdoc).Shapes.Range(Array("FinishButton")).Select
Selection.Delete
Sheets(workdoc).Protect Password:="password"
Application.DisplayAlerts = False
Sheets(workdoc).Delete
Application.DisplayAlerts = True
Workbooks("Template.xlsm").Save
End Sub
Thank you
I am trying to keep the pictures in a table alongside the table once I delete the fist four columns. I have set each of their location properties to "Move and Size with Cells" however they still do not move when I do the above programatically (it works when done by manually)
Within my program I save a copy of the workbook, enter into that workbook and delete the first four columns, and then save that workbook to html. Unfortunately when I delete the first four columns, the photos never move alongside them.
'Sets which sheets to search through and update
sheetList = Array("CH01", "CH02", "CH03", "CH04", "CH05", "CH06", "CH07",
"CH08", "CH09")
Application.ScreenUpdating = False
'Saves and opens new workbook to process and convert to html. Workbook
name is skew number.xlsm
ActiveWorkbook.SaveCopyAs _
Filename:=ActiveWorkbook.Path & "\test.xlsm"
Workbooks.Open (ActiveWorkbook.Path & "\test.xlsm")
For sheetNum = LBound(sheetList) To UBound(sheetList)
'sets sh to each sheet in sheetList
Set sh = ActiveWorkbook.Sheets(sheetList(sheetNum))
'Deletes first four rows of each sheet in sheetList (only way to
successfully hide columns once converted to html)
sh.Columns(1).EntireColumn.Delete
sh.Columns(1).EntireColumn.Delete
sh.Columns(1).EntireColumn.Delete
sh.Columns(1).EntireColumn.Delete
Next
Application.Wait (Now + TimeValue("0:01:00"))
ActiveWorkbook.Save
'Saves temp workbook as html
ActiveWorkbook.SaveAs _
Filename:=ActiveWorkbook.Path & "\test.html", _
FileFormat:=xlHtml
ActiveWorkbook.Close False
Application.ScreenUpdating = True
As you can see, I have even made the program wait for a minute to give the photos a chance to update their position. I have also kept the screen from updating until the entire process is done, which was the only suggestion I found on another thread. I also set each picture property to "xlMoveAndSize" in a previous bit of code, and I am sure that their location preference is updating to that.
Try something like this - activating each sheet may allow for the shapes to mave as the columns are deleted.
Dim sheetList, wbCopy As Workbook, copyName As String
Dim wbOrig As Workbook, shtName
'Sets which sheets to search through and update
sheetList = Array("CH01", "CH02", "CH03", "CH04", "CH05", _
"CH06", "CH07", "CH08", "CH09")
Set wbOrig = ActiveWorkbook
copyName = wbOrig.Path & "\test.xlsm"
wbOrig.SaveCopyAs Filename:=copyName
Set wbCopy = Workbooks.Open(copyName)
wbCopy.Activate
For Each shtName In sheetList
With wbCopy.Sheets(shtName)
.Activate
DoEvents
.Range("A1:D1").EntireColumn.Delete
DoEvents
End With
Next
Application.Wait Now + TimeValue("0:00:10")
With wbCopy
.Save
.SaveAs Filename:=Replace(copyName, ".xlsm", ".html"), _
FileFormat:=xlHtml
.Close False
End With
The following code results in an .xls with the 2 worksheets I want. Only I don't end up with just values.. the formatting is in there (and I don't think it should be. paste. values. dammit.), and the .xls has a unbreakable link to the original document that doesn't need to be there (and I'm thinking shouldn't be there). All the cells only contain values and do not contain any of the equations contained in the source workbook.
When I open the newly created .xls I receive the message "the file format and extension of [ws name].xls don't match. The file could be corrupted or unsafe. Unless you trust its source, don't open it. do you want to open it anyway?"
I loathe the lack of trust.. :)
What am I doing wrong?
Sub QUOTE_ITEM_OUTPUT()
Dim ws As Worksheet
Dim Filename As String
Dim Filelocation As String
Dim UserName As String
Dim Password As String
Filename = Worksheets("CALCULATION PAGE").Range("ITEMNUM").Value & "_" & Worksheets("CALCULATION PAGE").Range("PDFSAVEREV").Value & ".xls"
Filelocation = "\\GSWGS\Apps\Global\FILES\Import\GWS-Upload-TST\"
With Application
.ScreenUpdating = False
' Copy specific sheets
Sheets(Array("ITEM OUTPUT", "ROUTING")).Copy
' Paste sheets as values
For Each ws In ActiveWorkbook.Worksheets
ws.Cells.Copy
ws.[A1].PasteSpecial Paste:=xlValues
Application.CutCopyMode = False
Cells(1, 1).Select
ws.Activate
Next ws
Cells(1, 1).Select
ActiveWorkbook.SaveCopyAs Filelocation & Filename
ActiveWorkbook.Close SaveChanges:=False
.ScreenUpdating = True
End With
End Sub
You are saving as .xls file, but have not specified that file format in the saveAs method. That's why you are getting security warnings...
You need to specify that parameter in the SaveAs method.
ActiveWorkbook.SaveAs Filename:=Filelocation & Filename, FileFormat:=56
Here is a link to MSDN page for the various fileFormat parameters:
https://msdn.microsoft.com/en-us/library/office/ff198017.aspx
EDIT - for second problem you face:
As for the fact that formats are being carried across, that is because you are not using the correct Enumeration value.
ws.[A1].PasteSpecial Paste:=xlValues
should be:
ws.[A1].PasteSpecial Paste:=xlPasteValues
Use another sub to 'cleanse' the sheet
Sub ApplyValuesTo(ByVal sh As Excel.Worksheet)
For Each cell In sh.UsedRange.Cells
With cell
.Value = .Value
'// This may take a while; the next line will allow you to manually
'// break if needed (e.g. If you have a lot of data in the sheet)
DoEvents
End With
Next
End Sub
I have an Excel workbook in which almost everything is automated. It opens other workbooks, copies data from them, closes them and then loops through the data several times to generate reports that we print and use. Almost every time after running all the VBA and then trying to print, print preview gets stuck either finding the printer or loading page sizes as seen in the picture. Closing Excel and reopening the document restores print preview to normal functionality. The only thing related to printing that the VBA does is change the print area. I have not had this issue with any other documents that run VBA. Is this just a bug or possibly something in the code?
This is the code that causes print preview to fail to load in some way. If I skip this section then it works as intended... I would like to have this code function in some way as it's still needed.
Set wb1 = Workbooks.Open(FileName)
Set wb2 = ThisWorkbook
For i = LBound(sArray) To UBound(sArray) 'Loops through array, copies available data from last report
ShtName = sArray(i, 0)
On Error Resume Next
wb1.Sheets(ShtName).Activate
If Err.Number = 0 Then
wb1.Sheets(ShtName).Activate
Columns("A:U").Copy
wb2.Sheets(ShtName).Activate
Columns("BE:BV").Select
Selection.PasteSpecial xlPasteValues
Application.CutCopyMode = False
lastrow = Cells(Rows.Count, "BE").End(xlUp).Row
Range("BA2:BC2").Select
Selection.AutoFill Destination:=Range(Cells(2, "BA"), Cells(lastrow, "BC")), Type:=xlFillDefault
End If
On Error GoTo 0
DoEvents
Next i
wb1.Close False
Sheet2.Activate
I've tried commenting out "On Error Resume Next", "On Error Goto 0", "If...", "End If", and "DoEvents". Print Preview still fails with those removed and just doing the copy and paste from the previous sheet.
It seems that removing all instances of DoEvents has fixed the issue...
Print Preview works correctly and Excel does not crash when exiting the workbook anymore.
I believe you're looking for some type of refresh action that can re-sync the preview display with the data on the sheet. You might want to try this at the end:
ActiveSheet.EnableCalculation = False
ActiveSheet.EnableCalculation = True
If that doesn't work, see if manually saving fixes the issue. You can try calling Application.Save at the end.
"Print preview occurs automatically when you choose File --> Print. Another option is to use the Page Layout view (the icon on the right side of the status bar). To get the old-style print preview, you need to use VBA. The following statement displays a print preview of the active sheet: ActiveSheet.PrintPreview "
Quoted from Microsoft Excel 2013 Power Programming with VBA by John Walkenbach, pages 956-957.
That being said, I tested your issue above by recording a relatively complex macro that creates a new sheet, performs 25 automatic actions, and shows a print preview, then closes the print preview when I click OK on a MsgBox. I iterated the program to do this 1000 times. I never had an issue with the PrintPreview.
Its kind of a shot in the dark, but I tried cleaning up your code a little bit. See if that has any affect at all.
Sub Test()
Dim wb1 As Workbook, wb2 As Workbook
Dim ws1 As Worksheet, ws2 As Worksheet
Dim isWS As Boolean
On Error GoTo sub_err
Set wb1 = Workbooks.Open(Filename)
Set wb2 = ThisWorkbook
For i = LBound(sArray) To UBound(sArray) 'Loops through array, copies available data from last report
ShtName = sArray(i, 0)
isWS = True
Set ws1 = wb1.Sheets(ShtName)
If isWS Then
Set ws2 = wb2.Sheets(ShtName)
ws1.Columns("A:U").Copy
ws2.Columns("BE:BV").PasteSpecial xlPasteValues
Application.CutCopyMode = False
lastrow = ws2.Cells(ws2.Rows.Count, "BE").End(xlUp).Row
ws2.Range("BA2:BC2").AutoFill Destination:=ws2.Range(ws2.Cells(2, "BA"), ws2.Cells(lastrow, "BC")), Type:=xlFillDefault
End If
DoEvents
Next i
wb1.Close False
ws2.Activate
sub_exit:
Exit Sub
sub_err:
If Err.Number = 9 Then
isWS = False
Resume Next
Else
MsgBox "Error: " & Err.Number & vbNewLine & Err.Description
Resume sub_exit
End If
End Sub
The big thing I did was split off your error handling, this way it only resumes next when you don't find the sheet in wb1 and all other errors (none error 9 errors) will still show your error message.
I also made sure all your Range(), Cells(), and Columns() were referencing the correct sheet (just incase excel is getting confused) and I assumed the active sheet was the correct sheet, but you may want to verify this in the code to make sure it's doing the correct thing in the correct sheet.
Now the copy code only runs if isWS = true, and it will always be true unless an error 9 code is thrown. The only thing I didn't know was if wb2 would always have a sheet name equal to ShtName but I'm guessing it will since it's inside your if err.number = 0
I'm not sure if this will change anything for you, but I'd be curious to hear your results other way.