简体   繁体   中英

Special Copy Paste in VBA

This is a Copy Paste question using VBA. I basically want to grab a number from many different workbooks. My problem is this number is contantly updating so I don't think I can have the last vesion of the number without opening the workbooks. The workbooks are big and take time to open and load data (taking data from an external source (bloomberg)). My first clue was to open the workbooks, then let them charge then taking the data from it. My problem is, I need to set up a timer to do so(and let my workbook load) and during this timer my workbook cannot upload the datas so I end up with my old datas...

So the only solution I found was to do two different macros. One open all the workbook, then the second close and save it and grab the data from it...

Do you guys have any better idea?

My problem is, the workbooks are so big I need to open them 5 by 5 maximum and do it every time...

I copy paste you my code, I know it is very basic, if you think of any better code or way to make it work, please let me know.

Sub OpenWorkbooks()
workbooks.Open Filename :="C/.../file1.xlsx"
workbooks.Open Filename :="C/.../file2.xlsx"
workbooks.Open Filename :="C/.../file3.xlsx"
.
.
End sub 

Now the one to close and then copy paste the value as written by someone else.

Sub GetNumber()
Dim wWbPath As String, WbName As String
Dim WsName As String, CellRef As String
Dim Ret As String


Workbooks("file1").Close SaveChanges:=True

wbPath = "C:/etc...."

WbName = "file1.xlsx"
WsName = "Sheet1"
CellRef = "AD30"


arg = "'" & wbPath & "[" & wbName & "]" & _ 
wsName & "'!" & Range(cellRef).Address(True, True, xlR1C1) 

Worksheets("Sheet1").Range("A1") = ExecuteExcel4Macro(arg) 

End sub 

As said do you think there is a better way to do it? I wanted to do the whole steps for each file but I cannot since the timer stop the refresh of my spreadhseet and I need a timer since my worksheets needs time to load. So 1 - Open all , 2- close all and save all and copy the numbers... But I need to do it by batch cause if I open all it crashes...

My other question is, how could I make the code better? Ultimately I would like to have in my open workbook a spreadsheet where I would have all the paths for each worbook to open and copy/paste. then I would like a macro which loop the path, open the workbook wait (but timer not working...) then copy paste and close.

The altrnative is always looping the paths but by blocks. I will put all my paths on cells A1:A10 and I could have a loops opening the path present in A1:A10, then a second macro closing and saving the workbook with the path in A1:A10

Any ideas are welcome,

Thank you

You can achieve this in different ways. One is to store the values in a sheet or database and every time that you want to refresh and get new values compare the new value to the old value and if it was different (cell value updated for sure) then continue the code. Just to make the code get out of waiting you should set a max time like an expiration time. I would do an iteration of 20 times, each for 5 seconds. So basically you should have a setup like this in your code:

for i=1 to 20
    newHour = Hour(Now()) 
    newMinute = Minute(Now()) 
    newSecond = Second(Now()) + 5
    waitTime = TimeSerial(newHour, newMinute, newSecond) 
    ' ~~> get new value here and compare it to the old value

next i

Application.Wait waitTime


if newValue<>oldValue then
    exit for
else
    'do nothing, just wait
end if

or you can simply let Windows take the control, finish the task and continue:

'~~> your code here before refresh
Activeworkbook.RefreshAll
DoEvents
'~~> rest of your code here after refresh

DoEvents let's Windows to momentarily take a break from Macro to process all pending events before returning to the macro. That means it will refresh your workbook from the external resource and then continue executing the rest of code.

If you are using Excel 2010 and higher, there is a control that may work better than DoEvents:

 ThisWorkbook.RefreshAll 'or activeworkbook, choose as you need
 Application.CalculateUntilAsyncQueriesDone 'the code execution will halt here until the refresh job is done
Sub testopenRefreshClose()
    Call openRefreshClose("C/.../file1.xlsx")
    Call openRefreshClose("C/.../file1.xlsx")
End Sub
Sub openRefreshClose(wbPathName As String)
    Dim wb As Workbook

    Set wb = Workbooks.Open(wbPathName) ' open and assign to workbook object
    wb.RefreshAll ' refresh the data
    wb.Close SaveChanges:=True ' close the workbook
End Sub

This appears to finish running the query before closing, but you can also try unchecking enable background refresh which will ensure the data is updated before other actions are taken.

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM