【问题标题】:Special Copy Paste in VBAVBA中的特殊复制粘贴
【发布时间】:2017-12-05 16:33:35
【问题描述】:

这是一个使用 VBA 的复制粘贴问题。我基本上想从许多不同的工作簿中获取一个数字。我的问题是这个号码在不断更新,所以我认为如果不打开工作簿,我就无法拥有该号码的最后一个版本。 工作簿很大,打开和加载数据(从外部来源 (bloomberg) 获取数据)需要时间。 我的第一个线索是打开工作簿,然后让它们充电,然后从中获取数据。我的问题是,我需要设置一个计时器来这样做(并让我的工作簿加载),在这个计时器期间,我的工作簿无法上传数据,所以我最终得到了我的旧数据......

所以我找到的唯一解决方案是执行两个不同的宏。一个打开所有工作簿,然后第二个关闭并保存并从中获取数据...

你们有更好的主意吗?

我的问题是,工作簿太大了,我需要最多 5 x 5 打开它们,并且每次都这样做......

我复制粘贴我的代码,我知道这是非常基本的,如果您想到任何更好的代码或使其工作的方法,请告诉我。

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

现在关闭然后复制粘贴其他人写入的值。

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 

如前所述,您认为有更好的方法吗?我想为每个文件执行整个步骤,但我不能因为计时器停止刷新我的电子表格,我需要一个计时器,因为我的工作表需要时间来加载。 所以1-全部打开,2-全部关闭并保存并复制数字...但是我需要批量执行,因为如果我打开所有它会崩溃...

我的另一个问题是,我怎样才能使代码更好?最终,我希望在我打开的工作簿中有一个电子表格,其中我将拥有每个工作簿打开和复制/粘贴的所有路径。然后我想要一个循环路径的宏,打开工作簿等待(但计时器不起作用......)然后复制粘贴并关闭。

替代方案总是循环路径,但按块循环。我会将所有路径放在单元格 A1:A10 上,我可以有一个循环打开 A1:A10 中存在的路径,然后第二个宏关闭并使用 A1:A10 中的路径保存工作簿

欢迎任何想法,

谢谢

【问题讨论】:

  • 这个随便吧,不过很多语言都可以打开excel文件。您可能会发现以编程方式与另一种语言(可能是 python)交互的过程比为 Excel 本身编写宏要容易得多。这看起来像是对 python 的一个很好的介绍:automatetheboringstuff.com/chapter12.
  • @DanFarrell 感谢您的回复!不幸的是,它需要是 VBA 应用程序 Button 类型,因为我不会成为它的用户......我也更喜欢 Python......
  • 我们需要更多信息,但从你所写的内容来看,我认为你让事情变得困难。您应该只有一个代码可以一一打开工作簿并复制您需要的任何数据。这样,您将获得更新的数据,并且不需要太多内存。当您打开工作簿时,它们是否连接到一些需要更新的外部资源?
  • @Ibo 谢谢你的回复 那是我的问题。工作簿需要时间来刷新,因为真实的提要数据来自外部源。所以我需要设置一个计时器,以确保在我的宏副本的第二部分过去之前,工作簿可以很好地更新。问题是......在这个计时器期间,我的工作簿停止刷新。如果我设置了 10 秒的单圈时间,在这 10 秒内,我的工作簿也将停止刷新......所以不可能那样......
  • @DanFarrell 很难说使用 Python 自动化 Office 比使用 VBA 更容易。这就是 VBA 的目的。事实上,这可以说是 VBA 比 Python 更擅长的唯一项。

标签: vba excel


【解决方案1】:
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

这似乎在关闭之前完成了查询的运行,但您也可以尝试取消选中启用后台刷新,这将确保在采取其他操作之前更新数据。

【讨论】:

  • 感谢您的回复。不幸的是,由于某些原因,它没有刷新内部的 API 数据……在某些单元格中,有一个公式正在活跃地从外部获取数据。看起来这本书打开然后直接关闭而不更新它......有什么线索吗?
  • 或者它没有让足够的时间,所以而不是里面的价值,有#VALUE!因为它没有足够的时间来加载。我尝试按照 Ibo 的建议添加 Application.CalculateUntilAsyncQueriesDone,不幸的是它没有任何改变。 (连接属性为灰色)
【解决方案2】:

您可以通过不同的方式实现这一目标。一种是将值存储在工作表或数据库中,每次要刷新并获取新值时,将新值与旧值进行比较,如果不同(单元格值肯定已更新),则继续执行代码。只是为了让代码不再等待,您应该设置一个最大时间,例如过期时间。我会做 20 次迭代,每次 5 秒。所以基本上你应该在你的代码中有这样的设置:

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

或者您可以简单地让 Windows 控制,完成任务并继续:

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

DoEvents 让 Windows 在返回宏之前暂时从宏中休息一下以处理所有未决事件。这意味着它将从外部资源刷新您的工作簿,然后继续执行其余代码。

如果您使用的是 Excel 2010 及更高版本,则有一个控件可能比 DoEvents 工作得更好:

 ThisWorkbook.RefreshAll 'or activeworkbook, choose as you need
 Application.CalculateUntilAsyncQueriesDone 'the code execution will halt here until the refresh job is done

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-14
    • 2017-11-28
    • 1970-01-01
    相关资源
    最近更新 更多