VBA 插入数据到不应该的位置。

huangapple go评论95阅读模式
英文:

VBA inserting data where it should not

问题

  1. ' 创建一个VBA,将具有相同结构的4个工作表中的数据复制到另一个工作表中。在该工作表中,我有额外的两列YearMonth和SourceSheet。SourceSheet列应包含数据来自于哪个4个工作表中的信息,yearmonth是根据计算工作表的单元格F1中选择的月份填充的。问题在于,yearmonth和sourcesheet列继续将数据放在它们不应该存在的地方。例如,第298行是最后一行,除了sourcesheet和yearmonth之外,所有其他列都正常,但由于某种原因,它们继续到第400行左右。
  2. ' 我主要使用chatgpt寻求帮助,因为我是VBA的初学者,它仍然给我提供了具有相同问题的代码。你能告诉我错在哪里吗?
  3. ' 以下是代码:
  4. Sub CopyDataToDataSheet()
  5. '...(以下代码未提供,可以在此处添加)
  6. End Sub
英文:

So Im trying to create a VBA that copies data from 4 sheets that have the same structure into another sheet and in that sheet I have extra two columns YearMonth and SourceSheet. The sourcesheet column should contain info from which of the 4 sheets the data is from and yearmonth is populated based on the selected month from cell F1 of calculation sheet. Problem is that the yearmonth and sourcesheet columns continue putting data all the way down where they shouldn't be. So for example row 298 is the last one and all other columns are fine except the sourcesheet and yearmonth which continue to row 400 something for some reason.

Im mainly using chatgpt for help as Im beginner with VBA and it still gives me a code that has the same issue. Can you help me what is wrong?

The code is:

  1. Sub CopyDataToDataSheet()
  2. Dim dataSheet As Worksheet
  3. Dim inputSheet As Worksheet
  4. Dim calculationSheet As Worksheet
  5. Dim lastRow As Long
  6. Dim yearMonthValue As Variant
  7. Dim confirmation As Integer
  8. Dim yearMonthColumn As Range
  9. Dim sourceSheetColumn As Range
  10. Dim dataRange As Range
  11. Dim sourceSheetNames As Variant
  12. Dim dataLastRow As Long`
  13. ' Set the data sheet
  14. Set dataSheet = ThisWorkbook.Worksheets("Data Archive")
  15. ' Unfilter the data sheet
  16. If dataSheet.AutoFilterMode Then
  17. dataSheet.AutoFilterMode = False
  18. End If
  19. ' Set the calculation sheet
  20. Set calculationSheet = ThisWorkbook.Worksheets("Calculation")
  21. ' Find the column index of "SourceSheet" in the data sheet
  22. Set sourceSheetColumn = dataSheet.Rows(1).Find("SourceSheet", LookIn:=xlValues, LookAt:=xlWhole)
  23. ' Loop through the input sheets
  24. sourceSheetNames = Array("sheet1", "sheet2", "sheet3", "sheet4")
  25. For Each inputSheet In ThisWorkbook.Worksheets(sourceSheetNames)
  26. ' Find the last row in the data sheet
  27. lastRow = dataSheet.Cells(dataSheet.Rows.Count, "A").End(xlUp).Row
  28. ' Copy the data from the input sheet to the data sheet
  29. Set dataRange = inputSheet.UsedRange.Offset(1)
  30. dataRange.Copy dataSheet.Cells(lastRow + 1, "A")
  31. ' Get the value from cell F1 of the Calculation sheet
  32. yearMonthValue = calculationSheet.Range("F1").Value
  33. ' Check if "SourceSheet" column exists
  34. If Not sourceSheetColumn Is Nothing Then
  35. ' Find the last row of imported data in column A
  36. dataLastRow = lastRow + dataRange.Rows.Count
  37. ' Assign the source sheet name to the "SourceSheet" column in the data sheet for each row
  38. dataSheet.Range(dataSheet.Cells(lastRow + 1, sourceSheetColumn.Column), dataSheet.Cells(dataLastRow, sourceSheetColumn.Column)).Value = inputSheet.Name
  39. ' Clear the remaining cells in the "SourceSheet" column below the imported data
  40. dataSheet.Range(dataSheet.Cells(dataLastRow + 1, sourceSheetColumn.Column), dataSheet.Cells(dataSheet.Rows.Count, sourceSheetColumn.Column)).ClearContents
  41. End If
  42. ' Find the column index of "YearMonth" in the data sheet
  43. Set yearMonthColumn = dataSheet.Rows(1).Find("YearMonth", LookIn:=xlValues, LookAt:=xlWhole)
  44. ' Check if "YearMonth" column exists
  45. If Not yearMonthColumn Is Nothing Then
  46. ' Assign the yearMonthValue to the "YearMonth" column in the data sheet for each row
  47. dataSheet.Range(dataSheet.Cells(lastRow + 1, yearMonthColumn.Column), dataSheet.Cells(dataLastRow, yearMonthColumn.Column)).Value = yearMonthValue
  48. ' Clear the remaining cells in the "YearMonth" column below the imported data
  49. dataSheet.Range(dataSheet.Cells(dataLastRow + 1, yearMonthColumn.Column), dataSheet.Cells(dataSheet.Rows.Count, yearMonthColumn.Column)).ClearContents
  50. End If
  51. ' Delete the data from the input sheet
  52. ' dataRange.ClearContents
  53. Next inputSheet
  54. ' Display success message
  55. MsgBox "Data imported successfully."
  56. End Sub`
  57. </details>
  58. # 答案1
  59. **得分**: 0
  60. 这是您提供的代码的翻译部分:
  61. ```vba
  62. 不清楚为什么你的结果差了数百行。您的数据可能存在一些奇怪的问题。有时在Excel中,当使用VBA中的“UsedRange”时,会捕获到不可见的数据或格式。因此,您可以尝试使用“ReallyUsedRange”函数,而不是`inputSheet.UsedRange`。例如,请参考这里:[getting-the-actual-usedrange](https://stackoverflow.com/questions/7423022/getting-the-actual-usedrange)
  63. 我在下面放置了代码的新版本。
  64. 关于ChatGPT的代码的一些想法:
  65. - 验证应该放在代码的早期,而不是在循环内部。因此,如果无法解析列索引,就不需要开始循环。
  66. - 您需要始终让用户知道什么时候出现了问题(即,如果验证失败)。
  67. - 另外,验证似乎有点武断 - 列经过验证,但未验证其他工作表是否存在,或者是否找到了正确的年份-日期值,或者输入数据是否具有正确的形状(列数)。也许所有这些都与ChatGPT的“指令”有关。
  68. - 复制的数据的行计数根本不起作用。
  69. - 它也没有正确处理空的输入工作表。
  70. - 我没有看到清除数据的理由,因为根据定义,它进入了最后一行,下面没有数据。
  71. - 如上所述,如果不小心使用“UsedRange”,它有点不可靠。
  72. - 我们的工作似乎仍然安全,至少目前如此:)尽管如此,ChatGPT的发展令人印象深刻,所以继续关注ChatGPT的发展。
  73. 新代码:
  74. Sub CopyDataTowsTarget()
  75. Dim wsTarget As Worksheet
  76. Dim wsSource As Worksheet
  77. Dim yearMonth As Variant
  78. Dim i As Long
  79. Dim j As Long
  80. Dim r As Range
  81. Dim s_col As Long
  82. Dim y_col As Long
  83. Dim arr
  84. &#39;先决条件
  85. &#39;名为DataArchive的工作表,具有A、B、C、D、SourceSheet、YearMonth列以及单元格A2:D10中的一些随机数据。
  86. &#39;名为Calculation的工作表,单元格F1中有'2023-05'。
  87. &#39;四个工作表sheet1、sheet2、sheet3、sheet4,其中单元格A2:D10中有随机数据(可能多或少几行)。
  88. &#39; 设置数据工作表
  89. Set wsTarget = ThisWorkbook.Worksheets(&quot;Data Archive&quot;)
  90. &#39; 仅为了在调试时加快进度
  91. &#39;wsTarget.Range(&quot;A11:J1000&quot;).Clear
  92. If wsTarget.AutoFilterMode Then
  93. wsTarget.AutoFilterMode = False
  94. End If
  95. yearMonth = Worksheets(&quot;Calculation&quot;).Range(&quot;F1&quot;).Value
  96. &#39; 获取MonthYear和SourceSheet列索引
  97. Set r = wsTarget.Rows(1).Find(&quot;SourceSheet&quot;, LookIn:=xlValues, LookAt:=xlWhole)
  98. If r Is Nothing Then
  99. MsgBox &quot;未找到源工作表列!&quot;
  100. Exit Sub
  101. Else
  102. s_col = r.Column
  103. End If
  104. Set r = wsTarget.Rows(1).Find(&quot;YearMonth&quot;, LookIn:=xlValues, LookAt:=xlWhole)
  105. If r Is Nothing Then
  106. MsgBox &quot;未找到年月列!&quot;
  107. Exit Sub
  108. Else
  109. y_col = r.Column
  110. End If
  111. &#39; 从输入工作表复制数据到存档工作表
  112. arr = Array(&quot;sheet1&quot;, &quot;sheet2&quot;, &quot;sheet3&quot;, &quot;sheet4&quot;)
  113. For Each wsSource In Worksheets(arr)
  114. i = wsTarget.Cells(wsTarget.Rows.Count, &quot;A&quot;).End(xlUp).Row + 1
  115. Set r = wsSource.UsedRange.Offset(1)
  116. If r.Rows.Count &gt; 1 Then
  117. Set r = wsSource.UsedRange.Offset(1)
  118. Set r = r.Resize(r.Rows.Count - 1)
  119. r.Copy
  120. wsTarget.Cells(i, &quot;A&quot;).PasteSpecial xlPasteValuesAndNumberFormats
  121. wsTarget.Cells(i, s_col).Resize(r.Rows.Count).Value = wsSource.Name
  122. wsTarget.Cells(i, y_col).Resize(r.Rows.Count).Value = yearMonth
  123. &#39; dataRange.ClearContents
  124. End If
  125. Next wsSource
  126. &#39; 显示成功消息
  127. MsgBox &quot;成功导入数据。&quot;
  128. End Sub

如果您的输入工作表没有标题,代码需要进行一些微调。如果您不想粘贴为值,请进行相应调整(我通常使用PasteSpecialxlPasteValuesAndNumberFormats,因为通常在存档时希望获取原始数据,而不必担心坏的公式引用)。

英文:

Its not clear why you got results off by hundreds of rows. There could be something weird in your data. Sometimes in Excel there is invisible data or even formatting that gets picked up when you use a "UsedRange" in VBA. So you could try bringing in a "ReallyUsedRange" function to use instead of inputSheet.UsedRange. See for example here: getting-the-actual-usedrange

I've put a new version of the code below.

Some thoughts on ChatGPT's code:

  • The validation should go earlier in the code, not inside the loop. So if the column indexes can't be resolved, no need to even start the loop.
  • You want to always let the user know when things didn't work correctly (i.e., if validation fails).
  • Also it seems a little arbitrary with the validation - columns are validated, but not whether other sheets exists, or a correct year-date value is found, or whether input data has the right shape (# of columns). Maybe all that has to do with your "instructions" for ChatGPT though.
  • The row counting of the data copied just didn't work.
  • It is not handling empty input sheets correctly either.
  • I don't see any reason to clear data below the data you copied in to the DataArchive, because by definition that went to the last row and their is no data below it.
  • As noted above UsedRange is a bit unreliable if you aren't careful and understand how you are using it.
  • Our jobs appear to be safe still, at least for now VBA 插入数据到不应该的位置。 Impressive nonetheless, so continuing to watch where ChatGPT goes.

New Code:

  1. Sub CopyDataTowsTarget()
  2. Dim wsTarget As Worksheet
  3. Dim wsSource As Worksheet
  4. Dim yearMonth As Variant
  5. Dim i As Long
  6. Dim j As Long
  7. Dim r As Range
  8. Dim s_col As Long
  9. Dim y_col As Long
  10. Dim arr
  11. &#39;Prequisites
  12. &#39; Sheet named DataArchive with columns A, B, C, D, SourceSheet, YearMonth and some random data in cells A2:D10
  13. &#39; Sheet named Calculation with &#39;2023-05&#39; in cell F1
  14. &#39; four sheets sheet1, sheet2, sheet3, sheet4 with random data in cells A2:D10 (may be a few more or less rows)
  15. &#39; Set the data sheet
  16. Set wsTarget = ThisWorkbook.Worksheets(&quot;Data Archive&quot;)
  17. &#39;only to make things go faster while debugging
  18. &#39;wsTarget.Range(&quot;A11:J1000&quot;).Clear
  19. If wsTarget.AutoFilterMode Then
  20. wsTarget.AutoFilterMode = False
  21. End If
  22. yearMonth = Worksheets(&quot;Calculation&quot;).Range(&quot;F1&quot;).Value
  23. &#39; Get the MonthYear and SourceSheet column indexes
  24. Set r = wsTarget.Rows(1).Find(&quot;SourceSheet&quot;, LookIn:=xlValues, LookAt:=xlWhole)
  25. If r Is Nothing Then
  26. MsgBox &quot;Source Sheet Column not Found!&quot;
  27. Exit Sub
  28. Else
  29. s_col = r.Column
  30. End If
  31. Set r = wsTarget.Rows(1).Find(&quot;YearMonth&quot;, LookIn:=xlValues, LookAt:=xlWhole)
  32. If r Is Nothing Then
  33. MsgBox &quot;Source Sheet Column not Found!&quot;
  34. Exit Sub
  35. Else
  36. y_col = r.Column
  37. End If
  38. &#39; Copy data from input sheets to Archive sheet
  39. arr = Array(&quot;sheet1&quot;, &quot;sheet2&quot;, &quot;sheet3&quot;, &quot;sheet4&quot;)
  40. For Each wsSource In Worksheets(arr)
  41. i = wsTarget.Cells(wsTarget.Rows.Count, &quot;A&quot;).End(xlUp).Row + 1
  42. Set r = wsSource.UsedRange.Offset(1)
  43. If r.Rows.Count &gt; 1 Then
  44. Set r = wsSource.UsedRange.Offset(1)
  45. Set r = r.Resize(r.Rows.Count - 1)
  46. r.Copy
  47. wsTarget.Cells(i, &quot;A&quot;).PasteSpecial xlPasteValuesAndNumberFormats
  48. wsTarget.Cells(i, s_col).Resize(r.Rows.Count).Value = wsSource.Name
  49. wsTarget.Cells(i, y_col).Resize(r.Rows.Count).Value = yearMonth
  50. &#39; dataRange.ClearContents
  51. End If
  52. Next wsSource
  53. &#39; Display success message
  54. MsgBox &quot;Data imported successfully.&quot;
  55. End Sub

If your input sheets do not have headers, the code needs a little tweaking for that. Also if you don't want the paste to be values adjust as well (I routinely use PasteSpecial with xlPasteValuesAndNumberFormats because usually for archiving you want the raw data without worry about bad formula references.

huangapple
  • 本文由 发表于 2023年5月25日 05:03:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76327388.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定