尝试将工作表复印并粘贴到单个工作表中,并使用不同的信息范围

时间:2015-11-02 20:58:34

标签: vba excel-vba excel

我有一张工作表允许选择一个部件号,并且它所经历的所有操作都被拉起,每个操作步骤都在不同的工作表上。我正在尝试创建的是基于什么操作将所有操作过程拉到一张要打印的页面中。并非所有操作都具有相同数量的步骤,并且并非每个部件都具有相同数量的操作。

我为第一个操作工作的代码,以及第二个操作的前3行。但是我不能把它全部拉下来。下面是我正在使用的代码。目前我只关注OP 1和2,一旦得到它,它必须能够在大约30种选择中进行16次不同的操作。

Dim rng As Range

If Sheets("Selection").Range("D3").Text = "N/A" Then
    Exit Sub
Else
    Set rng = Sheets(Sheets("Selection").Range("D3").Text).Range("A12:" & ActiveSheet.Range("S12").End(xlDown).Address)
    With rng
        .Copy
    End With
    With Sheets("Print FMEA").Range("S" & Rows.Count).End(xlUp).Offset(1, -18)
    .PasteSpecial xlPasteFormats
    .PasteSpecial xlPasteValues
    End With

End If

If Sheets("Selection").Range("D4").Text = "N/A" Then
    Exit Sub
Else
    Set rng = Sheets(Sheets("Selection").Range("D4").Text).Range("A12:" & ActiveSheet.Range("S12").End(xlDown).Address)
    With rng
        .Copy
    End With
    With Sheets("Print FMEA").Range("S" & Rows.Count).End(xlUp).Offset(1, -18)
    .PasteSpecial xlPasteFormats
    .PasteSpecial xlPasteValues
    End With

End If

End Sub

1 个答案:

答案 0 :(得分:0)

让我们先处理错误:

此行将引发错误Sheets("Print FMEA").Row (Lastrow + 1)。我不确定您尝试使用它做什么,但语法不正确。我有点惊讶你说这段代码对你有用。

此行只会选择数据到下一个空白单元格Set rng = Sheets(Sheets("Selection").Range("D4").Text).Range("A12:" & ActiveSheet.Range("S12").End(xlDown).Address)。您可能只获得前三行,因为第四行有空白。

要回答你的问题,我认为你需要分两个部分来考虑这个问题:

  1. 存储每项操作的参考详情。
  2. 遍历每个操作并处理详细信息。
  3. 您可以通过多种方式执行此操作,但Class对象可以正常运行。我给出了一个没有充分利用课程的例子,但它确实区分了这两个任务。

    因此,对于第1部分,插入一个新类( Insert~> Class Module )并将其命名为OpsFields。插入以下代码,用于存储工作表和单元格引用:

    Private mSourceSheet As Worksheet
    Private mRefSheet As Worksheet
    Private mRefFirstRange As Range
    
    Public Sub SetRefSheetAddress(sourceSheet As String, cellAddress As String)
        Dim sheetName As String
    
        Set mSourceSheet = ThisWorkbook.Worksheets(sourceSheet)
        sheetName = mSourceSheet.Range(cellAddress)
        Set mRefSheet = ThisWorkbook.Worksheets(sheetName)
    End Sub
    
    Public Sub SetFirstRefAddress(columnsAddress As String, firstRow As Long)
        Set mRefFirstRange = Intersect(mRefSheet.Columns(columnsAddress), _
                             mRefSheet.Rows(firstRow).EntireRow)
    End Sub
    
    Public Function GetDataRange()
        Dim r As Long
        Dim c As Long
        Dim lastRow As Long
        Dim rowCount As Long
    
        r = mRefSheet.Rows.Count
        c = mRefFirstRange.Columns(1).Column
        lastRow = mRefSheet.Cells(r, c).End(xlUp).Row
        rowCount = lastRow - mRefFirstRange.Rows(1).Row + 1
        Set GetDataRange = mRefFirstRange.Resize(rowCount)
    End Function
    

    然后您填充这些类并将它们存储到某种列表中 - 我已经使用了Collection,因为您不必对其进行重新定位,因此操作的数量并不是很重要。无所谓。在下面的代码中,我给了你一个两个例子,但你可以添加任意多个。此代码位于Module

    Private mOpsList As Collection 'at top of module
    
    
    
    Sub CreateOpsFields()
        Dim ops As OpsFields
    
        Set mOpsList = New Collection
    
        Set ops = New OpsFields
        ops.SetRefSheetAddress "Selection", "D3"
        ops.SetFirstRefAddress "A:S", 12
        mOpsList.Add ops
    
        Set ops = New OpsFields
        ops.SetRefSheetAddress "Selection", "D4"
        ops.SetFirstRefAddress "A:S", 12
        mOpsList.Add ops
    
    End Sub
    

    至于第2部分,您只需遍历您的类列表并执行粘贴任务,如下所示(再次在您的Module中):

    Sub RecordOps()
        Dim outputSheet As Worksheet
        Dim ops As OpsFields
        Dim data As Range
        Dim nextBlankRow As Long
    
        Set outputSheet = ThisWorkbook.Worksheets("Print FMEA")
        nextBlankRow = outputSheet.Cells(outputSheet.Rows.Count, "S").End(xlUp).Row
        For Each ops In mOpsList
            Set data = ops.GetDataRange
            data.Copy
            With outputSheet.Cells(nextBlankRow, "A").Resize(data.Rows.Count, data.Columns.Count)
                .PasteSpecial xlPasteFormats
                .PasteSpecial xlPasteValues
            End With
            nextBlankRow = nextBlankRow + data.Rows.Count
        Next
    End Sub
    

    您可以通常的方式调用这些例程。一种显而易见的方法是在某种 Initialisation 例程中填充类,然后在触发某个事件时调用粘贴例程。我只是将两个调用放在一个例程中,因此您可以看到语法:

    Sub RunMe()
        CreateOpsFields
        RecordOps
    End Sub