У меня есть главный лист (CMRDETAILS), я беру определенные данные из определенных столбцов двух других листов (HistoricalData) (ImportData) и копирую их в главный лист.
Я пытаюсь и не могу найти цикл, чтобы найти последнюю пустую ячейку и ввести данные в эту строку и пустые строки, следующие за ней. Первый набор данных, которые я перемещаю, является историческим, затем копирую и вставляю из Importdata
Есть ли способ однажды узнать диапазон, чтобы установить диапазон вставки для использования счетчика?
Private Sub CommandButton1_Click()
Dim ws As Worksheet
Dim filter As String
Dim targetWorkbook As Workbook, wb As Workbook
Dim Ret As Variant
Dim Caption As String
Dim LR2 As Long
Dim LR1 As Long
Dim LastCell As Range
Dim LastCellColRef As Long
Worksheets("ImportData").Cells.Clear
Set targetWorkbook = Application.ActiveWorkbook
filter = "Text files (*.CSV),*.CSV"
Caption = "Please Select an input file "
Ret = Application.GetOpenFilename(filter, , Caption)
If Ret = False Then Exit Sub
Set wb = Workbooks.Open(Ret)
wb.Sheets(1).UsedRange.Copy targetWorkbook.Worksheets("ImportData").Range("A1")
wb.Close SaveChanges:=False
Set ws = ThisWorkbook.Sheets("ImportData")
Worksheets("ImportData").Range("D:D").EntireColumn.Insert Shift:=xlToRight
Worksheets("ImportData").Range("D1").Value = "Month"
LR1 = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
LR2 = ws.Range("D" & ws.Rows.Count).End(xlUp).Row + 1
ws.Range("D" & LR2 & ":D" & LR1).FormulaR1C1 = "=TEXT(R[0]C[-1], ""mmm"")"
Sheets("HistoricalData").Range("AE2:AE51").Copy Sheets("CmrDetails").Range("B2:B51")
Sheets("HistoricalData").Range("D2:D51").Copy
Sheets("CmrDetails").Range("A2:A51").PasteSpecial xlPasteValues
Sheets("HistoricalData").Range("Z2:Z51").Copy Sheets("CmrDetails").Range("c2:c51")
LastCellColRef = 1 'column number to look in when finding last cell
Set LastCell = Sheets("CmrDetails").Cells(Rows.Count, LastCellColRef).End(xlUp).Offset(1, 0)
MsgBox LastCell.Address 'just to verify the count is working
Sheets("ImportData").Range("X2:X350").Copy Sheets("CmrDetails").Range("B52:B350") 'this is the data is want to copy to the empty row
Sheets("ImportData").Range("D2:D51").Copy 'this is the data is want to copy to the empty row
Sheets("CmrDetails").Range("A52:A350").PasteSpecial xlPasteValues 'this is the data is want to copy to the empty row
Sheets("ImportData").Range("AX2:AX350").Copy Sheets("CmrDetails").Range("c52:c350") 'this is the data is want to copy to the empty row
Application.CutCopyMode = False
Sheets("CmrDetails").Range("C2:C350").EntireColumn.Hidden = True
Set ws = ThisWorkbook.Sheets("NPS")
Set LastCell = Nothing
MsgBox ("Upload Complete")
End Sub
ошибок нет, я просто не могу понять логику
Вместо того, чтобы искать последнюю использованную ячейку, мы можем просто получить последнюю использованную строку.
LastRow = Sheets("CmrDetails").Cells(Sheets("CmrDetails").Rows.Count, 1).End(xlUp).Row + 1
Теперь мы можем изменить копирование данных из ImportData на динамическое, а вставку в CmrDetails сделать в первой открытой строке после вставки из HistoricalData.
Поскольку я не знаю, как выглядит ваш лист, все столбцы копируются в последнюю строку ImportData, хранящуюся в LR1. Если разные столбцы в ImportData заканчиваются на разных строках, вы можете вычислить каждую конечную строку так же, как вы это делали для LR1, и обновить код копирования. Это может быть особенно проблемой для столбца D, основанного на исходном коде.
Sheets("ImportData").Range("X2:X" & LR1).Copy Sheets("CmrDetails").Range("B" & LastRow & ":B" & LastRow + LR1 - 1)
Sheets("ImportData").Range("D2:D" & LR1).Copy
Sheets("CmrDetails").Range("A" & LastRow & ":A" & LastRow + LR1 - 1).PasteSpecial xlPasteValues
Sheets("ImportData").Range("AX2:AX" & LR1).Copy Sheets("CmrDetails").Range("C" & LastRow & ":C" & LastRow + LR1 - 1)
Быстрое решение
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim iws As Worksheet: Set iws = wb.Sheets("ImportData")
Dim dws As Worksheet: Set dws = wb.Sheets("CmrDetails")
Dim irg As Range: Set irg = iws.Rows("2:350")
Dim drg As Range: Set drg = dws.Cells(dws.Rows.Count, "A").End(xlUp) _
.Offset(1).EntireRow.Resize(irg.Rows.Count)
iws.Columns("X").Copy Destination:=dws.Columns("B")
dws.Columns("A").Value = iws.Columns("D").Value ' only values
iws.Columns("AX").Copy Destination:=dws.Columns("C")
Улучшение
Private Sub CommandButton1_Click()
ImportCsvData
End Sub
Sub ImportCsvData()
Const PROC_TITLE As String = "Import CSV Data"
' Define constants.
Const SRC_FILE_FILTER As String = "Text files (*.CSV),*.CSV"
Const SRC_DIALOG_TITLE As String = "Source File Selection"
Const INP_SHEET_NAME As String = "ImportData"
Const INP_FIRST_CELL As String = "A1"
Const INP_INSERT_COLUMN As String = "D"
Const INP_INSERT_COLUMN_FORMULAR1C1 As String = "=TEXT(R[0]C[-1], ""mmm"")"
Const COPY_SHEET_NAME As String = "HistoricalData"
Const DST_SHEET_NAME As String = "CmrDetails"
Const DST_LAST_ROW_COLUMN As String = "A"
Const FIRST_ROWS As String = "2:51" ' 50 rows
Const SECOND_ROWS As String = "52:350" ' 349 rows, maybe "52:351"?
' Destination
' Reference the destination workbook.
Dim dwb As Workbook: Set dwb = ThisWorkbook ' workbook containing this code
' Reference the Input sheet and clear it.
Dim iws As Worksheet: Set iws = dwb.Sheets(INP_SHEET_NAME)
iws.UsedRange.Clear
' Let the user select a file.
Dim sFilePath As Variant: sFilePath = Application.GetOpenFilename( _
FileFilter:=SRC_FILE_FILTER, Title:=SRC_DIALOG_TITLE)
If sFilePath = False Then
MsgBox "No file selected!", vbExclamation, PROC_TITLE
Exit Sub
End If
Application.ScreenUpdating = False
' Copy data from the Source sheet to the Input sheet.
Dim swb As Workbook: Set swb = Workbooks.Open( _
Filename:=sFilePath) ' if necessary, try with 'Local:=True'
Dim ifCell As Range: Set ifCell = iws.Range(INP_FIRST_CELL)
swb.Sheets(1).UsedRange.Copy ifCell
swb.Close SaveChanges:=False
' Destination
' Insert the specified column and populate it with the header
' and formulas from the 2nd to the last row.
iws.Columns(INP_INSERT_COLUMN).EntireColumn.Insert Shift:=xlToRight
With ifCell
Dim iLR As Long:
iLR = iws.Cells(iws.Rows.Count, .Column).End(xlUp).Row
With .EntireRow.Columns(INP_INSERT_COLUMN)
.Value = "Month" ' write header
.Offset(1).Resize(iLR - 1) _
.FormulaR1C1 = INP_INSERT_COLUMN_FORMULAR1C1 ' write formulas
End With
End With
' Reference the Copy and Destination sheets.
Dim cws As Worksheet: Set cws = dwb.Sheets(COPY_SHEET_NAME)
Dim dws As Worksheet: Set dws = dwb.Sheets(DST_SHEET_NAME)
' Reference the first entire row ranges (the same rows).
Dim crg As Range: Set crg = cws.Rows(FIRST_ROWS)
Dim drg As Range: Set drg = dws.Rows(FIRST_ROWS)
' Copy the first ranges (Copy to Destination).
crg.Columns("AE").Copy Destination:=drg.Columns("B")
drg.Columns("A").Value = crg.Columns("D").Value ' only values
crg.Columns("Z").Copy Destination:=drg.Columns("C")
' Reference the second entire row ranges.
Dim irg As Range: Set irg = iws.Rows(SECOND_ROWS)
Set drg = dws.Cells(dws.Rows.Count, _
DST_LAST_ROW_COLUMN).End(xlUp).Offset(1, 0) _
.EntireRow.Resize(irg.Rows.Count)
' Copy the second ranges (Input to 'first available' row in Destination).
irg.Columns("X").Copy Destination:=drg.Columns("B")
drg.Columns("A").Value = irg.Columns("D").Value ' only values
irg.Columns("AX").Copy Destination:=drg.Columns("C")
' Hide column 'C' in Destination.
dws.Columns("C").Hidden = True
Application.ScreenUpdating = True
' Inform.
MsgBox "Import complete.", vbInformation, PROC_TITLE
End Sub
Если остальное в порядке, это может означать, что в строках от 52
до 350
в столбцах A
, D
и AX
листа ввода нет данных. Кроме того, я проигнорировал, что ваш код копируется из D2:D51
в столбец A
почти 5
раз, считая это опечаткой, поскольку 2:350
— это 349
строки. Пожалуйста, проверьте первое и уточните второе. Попробуйте удалить , Local:=True
, который в моем случае необходим, а я забыл его удалить.
спасибо, листы исторических данных имеют 44 записи/строки, входные данные имеют 3 строки, но с течением года будет увеличиваться и объем данных на обеих вкладках, хотя по идиотски, позволяя области включать до 350 строк, я планировал использовать данные расширение с течением года, теперь действительно рассматривая количество строк как функцию, означает ли вышеизложенное, что я могу ссылаться только на одну строку code
Const FIRST_ROWS As String = "2:51" ' вместо Const FIRST_ROWS As String = "2:51 " ' 50 строк Const SECOND_ROWS As String = "52:350"
я сопоставил две _rows, и это работает 'FIRST_ROWS As String = "2:51" ' 50 строк Const SECOND_ROWS As String = "2:51" - спасибо, что нашли время, чтобы помочь мне
Я попробовал код «Улучшение», очень ценю усилия, похоже, он не копирует данные на листе «ImportData» и не помещает их на лист «CmrDetails».