【问题标题】:Excel VBA PasteSpecial not pasting consistentlyExcel VBA PasteSpecial 粘贴不一致
【发布时间】:2017-02-02 14:42:42
【问题描述】:

我有一份报告,用于导入与工作计划相关的数据,然后根据数据创建图表和统计数据。计算和图表基于表格,表格由 VBA 填充 - 用户选择文件,然后 VBA 检查它是否与预期的文件格式匹配并将所有内容放在正确的位置。

但是,代码的 pastespecial 部分不能正确粘贴所有内容。具体来说,有许多列带有日期值,当粘贴其中一些列(不是一列或特定行,而是看似随机的单元格)时,粘贴时没有格式化为日期,因此当我在特定时间范围内寻找工作时,不会在公式中捕获。

在源文件中,所有数据 100% 保存为日期值(如果我对数据进行过滤,则全部按年份分组,如果我使用测试单元格,则可以扩展到月/日/时间 +将 1 添加到显示下一个日期的单元格中)。一旦粘贴到目标工作表中,有些仍然是日期值,但有些似乎是文本并显示为 dd/mm/yyyy hh:mm 但在计算中被遗漏。在这些单元格上,如果我进入它们,请按 F2,然后按 Enter,然后单元格将更改为日期值(向右重新对齐,然后包含在日期范围公式中)。

代码如下:

Public Sub importdata()
Dim wb1, wb3 As Workbook
Dim ws1, ws3 As Worksheet
Dim lrow As Long
Dim WOtable As ListObject
Dim searchcell As Range

Set wb1 = ThisWorkbook
Set ws1 = wb1.Sheets("Dashboard")
Set WOtable = ws1.ListObjects("workorder")

WOfile = Application.GetOpenFilename(FileFilter:="Excel Files (*.CSV),*.CSV", Title:="Select Workorder Extract To Be Opened",MultiSelect:=False)
If WOfile = False Then Exit Sub
Set wb3 = Workbooks.Open(WOfile)
Set ws3 = wb3.Sheets(1)

ws3.Range("M:M, O:O, Q:Q").EntireColumn.Delete
   If ws3.Range("A1").Value = "jobnumber" And ws3.Range("B1").Value ="jobdesc" And etc etc Then
   lrow = ws3.Range("A1").End(xlDown).Row
    ws3.Range("A2:O" & lrow).Copy
   WOtable.DataBodyRange(1, 1).PasteSpecial Paste:=xlPasteValuesAndNumberFormats, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
   Application.CutCopyMode = False
   Else: MsgBox ("File selected to import workorder information was not in expected format, please check the file and retry.")
End If

wb3.Close False

End Sub

我尝试在复制之前添加以下行,以根据我在 google 上看到的内容强制它,但无济于事:

ws3.Columns("E:K").NumberFormat = "DD/MM/YYYY HH:MM:SS"

感谢您的帮助

【问题讨论】:

  • 您可以使用默认参数对相关列运行文本到列,以对整个列执行相当于 F2/Enter 的操作 - 这可以通过编程方式完成。
  • 使用复制和粘贴在工作簿中移动数据非常混乱且容易出错,因为您使用单个剪贴板(用于整个操作系统)来移动信息。例如。如果您有多个进程正在运行并使用剪贴板,您将遇到将另一个进程数据粘贴到您期望其他内容的位置的情况。您是否尝试过将信息复制到数组中,然后将该数组写回您想要信息的工作表? (它还将保留类型,并且您不会争用剪贴板)。
  • @765tgs 啊,我明白了,也许这引起了问题。我没有尝试这样做,也没有这样做过,如果您知道任何可以让我学习如何做到这一点的好资源,那么如果您能分享,我将不胜感激,否则我会尝试在谷歌上找到一些东西。谢谢
  • @Zerk 感谢您的回复。 765tgs 提出了一种不同的复制数据的方式可能是一个很好的前进方式,但是如果这不起作用,那么我将在使用文本粘贴到列后考虑修复它。这可以在桌子上工作吗?
  • @SMLBW 正如 765tgs 所建议的那样,通过数组传输是更可取的,尽管出于其他原因,例如内存中的数据操作而不是表上的数据。这两种方法都工作得很好,我可以确认数组方法似乎保持了快速测试的日期格式。我将通过示例方法为您发布答案。文本到列的方法可以在表格上完成,但您在循环中遍历列。

标签: excel vba copy-paste


【解决方案1】:

正如 cmets 中所讨论的,将数据推送到变体数组然后将其粘贴到目标的示例用法。几个cmets:

  • 始终为每个变量说明您想要的类型,同一行中的逗号分隔变量不会全部采用最后一种类型。
  • 使用 with 语句可以使代码稍微干净一些,并减少 excel 需要解析的引用量。
  • 由于您没有清除表的内容(只是覆盖了它们),因此我在代码中复制了这种行为,因为我认为这是预期的。

编辑子:

Public Sub importdata()
Dim wb1 As Workbook, wb3 As Workbook
Dim ws1 As Worksheet, ws3 As Worksheet
Dim WOtable As ListObject
Dim varTMP As Variant

Set wb1 = ThisWorkbook
Set ws1 = wb1.Sheets("Dashboard")
Set WOtable = ws1.ListObjects("workorder")

WOfile = Application.GetOpenFilename(FileFilter:="Excel Files (*.CSV),*.CSV", Title:="Select Workorder Extract To Be Opened", MultiSelect:=False)
If WOfile = False Then Exit Sub
Set wb3 = Workbooks.Open(WOfile)
Set ws3 = wb3.Sheets(1)

With ws3
    .Range("M:M, O:O, Q:Q").EntireColumn.Delete
    If .Range("A1").Value = "jobnumber" And .Range("B1").Value ="jobdesc" And etc etc Then
        'load data into variant array
        varTMP = .Cells(1, 1).CurrentRegion
        'If you want to do any data manipulation on the array, do it here
        'Paste array
End With
        With WOtable.DataBodyRange
            Range(.Cells(1, 1), .Cells(0 + UBound(varTMP, 1), 0 + UBound(varTMP, 2))) = varTMP
        End With
    Else
        MsgBox ("File selected to import workorder information was not in expected format, please check the file and retry.")
    End If

wb3.Close False

End Sub

【讨论】:

  • 非常感谢您的回答!几个问题。首先,当我去加载这些数据时,表格已经是空白的了——这会改变你给出的第三个要点的建议吗?其次,我是否需要调整 (1,1).CurrentRegion 行,以便将正确数量的行和列拉入数组中,还是 currentregion 位做出一些假设?
  • 1) 表格为空白很好。 2) CurrentRegion(msdn.microsoft.com/en-us/library/office/ff196678.aspx) 将选择整个数据集,如果其中没有任何空白行或列(管理良好的数据不应该有这些)。如果它们存在并且无法删除它们,则使用标准方法指定您的范围。
  • 谢谢。可能有空白的行和列(从单独的作业计划软件导出数据时,其他用户可能无法正确提炼提取的数据)。您认为假设有 15 列(这是固定的)并且我插入行 lrow = ws3.Range("A1") 行 varTMP = .Cells(2, 1).offset(15,lrow-1) .End(xlDown).Row 事先?将回到我的电脑,明天可以进行测试。谢谢
  • 如果是这种情况,那么 xldown 将面临同样的空白问题。而是使用 lrow = .Cells(.Rows.Count,"A").End(xlUp).row 然后定义数组如下: varTMP = range(.cells(2,1),.cells(lrow,15) )
  • 我只能测试您的建议,不幸的是,通过数组方法复制数据并没有解决问题。我做了更多的测试,无论我使用哪种方法,其中包含日期值的某些单元格都会复制为文本而不是数字。您是否碰巧知道其他可能导致此问题的原因?
猜你喜欢
  • 2023-03-04
  • 1970-01-01
  • 2013-03-14
  • 1970-01-01
  • 2015-07-29
  • 2013-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多