首页 > 常识 >

综合单价的计算公式excel(Excel VBA 工程项目报价表数据提取整理/格式调整)

时间: 2024-11-04 09:03:21


内容提要

大家好,我是冷水泡茶,有位粉丝朋友在文章【Excel VBA 按同一个项目合并单元格文字】下面留言:

说实话,看文字还真没看明白,我就让他把文件发我瞅瞅,原来他是要把工程报价表中的C列的部分文字合并,填到D列(插入列),他的源表是这样的:

中间还有一个分页:

他的需求表是这个样子的:

我经过一番研究,分析他原来数据的规律,正如他所说,跟我前面分享的案例有几分相似,我们一起来看一看吧

基本思路

1、把不需要的标题删除,我们可以通过删除B列为空的行。

2、目标表的表头字段与原表的表头字段不完全一样,索性删除重新添加,可以通过查找关键字的方法定位到表头行,将其删除。

3、最难的地方,是把B列为空的单元格,对应的C列单元格的字符连起来,还要跳过两个工程名称行。

4、在C列后面插入一列,把拼接好的字段填到D列对应的项目名称行。

5、把B列为空的行,除了两个工程名称行,统统删除。

程序代码

1、ManipulateData,操作数据:

Sub ManipulateData()
    Dim sourceWs As Worksheet
    Dim targetWs As Worksheet
    Dim wsName As String
    Dim lastRow As Integer
    Dim tbTitle(), strMerge As String
    Dim rng As Range
    Dim arrWidth()
    Application.ScreenUpdating = False
    Set sourceWs = ThisWorkbook.ActiveSheet
    arrWidth = Array(5, 15, 15, 50, 8, 10, 12, 16)
    wsName = "清洗表"
    If sourceWs.Name = wsName Then Exit Sub
    tbTitle = Array("序号", "项目编码", "项目名称", "项目特征描述", "计量单位", "工程量", "综合单价", "合价")
    Call CopyWorksheet(sourceWs, wsName)
    '删除小计行以下的行
    Set targetWs = ThisWorkbook.Sheets(wsName)
    With targetWs
        lastRow = targetWs.UsedRange.Rows.Count
        For i = lastRow To 1 Step -1
            If Cells(i, 3) = "" Then
                Rows(i).Delete
            End If
        Next
        For i = lastRow To 1 Step -1
            If InStr(Cells(i, 3), "小") > 0 And InStr(Cells(i, 3), "计") > 0 Then
                Rows(i & ":" & lastRow).Delete
            End If
        Next
        For i = lastRow To 1 Step -1
            If InStr(Cells(i, 3), "名称") > 0 And InStr(Cells(i, 3), "特征") > 0 Then
                Rows(i).Delete
            End If
        Next
        .Columns(4).Insert Shift:=xlToRight
        .Columns("I:I").Delete
        .Rows(1).Insert Shift:=xlDown
        .Range("A1").Resize(1, UBound(tbTitle) + 1) = tbTitle
        lastRow = targetWs.UsedRange.Rows.Count
        For i = 4 To lastRow
            If .Cells(i, 2) <> .Cells(i - 1, 2) Then
                m = i
                If .Cells(i, 2) <> "" Then
                    k = i
                End If
            End If
            If .Cells(i, 2) <> .Cells(i + 1, 2) Then
                If .Cells(i, 2) = "" Then
                    If InStr(Cells(i, 3), "工程") > 0 Then
                        n = i - 1
                    Else
                        n = i
                    End If
                    For j = m To n
                        strMerge = strMerge & .Cells(j, 3) & Chr(10)
                    Next
                    strMerge = Left(strMerge, Len(strMerge) - 1)
                    .Cells(k, 4) = strMerge
                    strMerge = ""
                End If
            ElseIf Cells(i + 1, 3) = "" Then
                n = i
                For j = m To n
                    strMerge = strMerge & .Cells(j, 3) & Chr(10)
                Next
                strMerge = Left(strMerge, Len(strMerge) - 1)
                .Cells(k, 4) = Trim(strMerge)
                strMerge = ""
            End If
            If .Cells(i, 3) = "" Then Exit For
        Next
        lastRow = .UsedRange.Rows.Count
        For i = lastRow To 3 Step -1
            If .Cells(i, 2) = "" Then
                If InStr(Cells(i, 3), "工程") = 0 Then
                    .Rows(i).Delete
                End If
            End If
        Next
        lastRow = .UsedRange.Rows.Count
        .Rows(2).ClearFormats
        With .Range(Cells(1, 1), Cells(lastRow, 3))
            .ClearFormats
            .VerticalAlignment = xlCenter
        End With
        With .Range(Cells(1, 6), Cells(lastRow, 8))
            .ClearFormats
            .VerticalAlignment = xlCenter
            .NumberFormatLocal = "_ * #,##0.00_ ;_ * -#,##0.00_ ;_ * ""-""??_ ;_ @_ "
        End With
        With .Cells(1, 1).Resize(lastRow, UBound(tbTitle) + 1)
            .Borders.LineStyle = xlDot            ' 边框线的样式为连续线
            .Borders.Weight = xlThin ' 边框线的粗细为细线
            .Borders.ColorIndex = xlAutomatic  ' 边框线的颜色为自动
        End With
        .Cells.Font.Size = 11
        .Rows(1).HorizontalAlignment = xlCenter
        .Columns(1).HorizontalAlignment = xlCenter
        For i = LBound(arrWidth) To UBound(arrWidth)
            .Columns(i + 1).ColumnWidth = arrWidth(i)
        Next
    End With
    Call DeleteButtons(targetWs)
    targetWs.Rows.AutoFit
    targetWs.Range("A1").Select
    Application.ScreenUpdating = True
End Sub

代码解析:

(1)定义一些变量

(2)把源工作表sourceWs设为当前活动工作表。

(3)arrWidth数组,存放目标表的列宽,最后完成的表的列宽就按照这个数组的值来顺序确定,可根据需要调整。

(4)设置目标表名称wsName,如果当前活动工作表的名称也等于wsName,说明源表不对,直接退出过程

(5)tbTitle ,存放新表头字段名称。

(6)Call CopyWorksheet 复制源工作表为目标工作表。

(7)把targetWs设为复制的新表,下面的操作均针对targetWs进行。

(8)通过循环,删除“所有空白行。这里要从下往上删除。

(9)通过循环,删除“小计”以下的所有行。这里他的小计中间有空格,我们用Instr函数判断是否同时包含“小”和“计”,不管有多少空格就不受影响了。

(10)通过循环,删除表头行。这里跟删除小计行差不多,判断是否包含“名称”和“特征“两个字段。

(11).Columns(4).Insert Shift:=xlToRight,在第4列也就是D列插入一列。删除多余的I列,有格式。

(12) .Rows(1).Insert Shift:=xlDown,第一行插入空白行。接着把tbTitle的字段写入第一行。

(13)从第4行开始循环,寻找定位需要组合字符的行,m表示开头,n表示结尾,k表示项目编码或项目名称行,后面字符组合完成后,填入D列,k行。

(14)拼接字符填充完毕后,把不需要的行删除,就是上面的m~n行,但我们在删除的时候,采用删除B列空行的方法,跳过工程名称那一行。

(15)接着,设置单元格的格式,包括对齐,划线,数字格式等。

(16)Call DeleteButtons,删除目标工作表中的所有按钮。

2、其他过程:CopyWorksheetDeleteButtons

Sub CopyWorksheet(sourceWorksheet As Worksheet, wsName As String)
    Dim targetWorksheet As Worksheet
    '检查是否存在同名的目标工作表,如果存在则删除
    On Error Resume Next
    Set targetWorksheet = ThisWorkbook.Worksheets(wsName)
    On Error GoTo 0
    If Not targetWorksheet Is Nothing Then
        Application.DisplayAlerts = False
        targetWorksheet.Delete
        Application.DisplayAlerts = True
    End If
    '复制源工作表到同一个工作簿
    sourceWorksheet.Copy After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
    '获取新复制的工作表的引用
    Set targetWorksheet = ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
    '重命名新复制的工作表
    targetWorksheet.Name = wsName
End Sub


Sub DeleteButtons(ws As Worksheet)
    Dim obj As OLEObject
    '循环遍历工作表上的所有 OLE 对象(包括命令按钮)
    For Each obj In ws.OLEObjects
        obj.Delete ' 删除命令按钮
    Next
End Sub

代码解析:

(1)CopyWorksheet,复制工作表,过程参数:源工作表sourceWorksheet,新工作表名wsName ,把“源工作表”复制成以“新工作表名”命名的工作表。

(2)DeleteButtons,删除目标工作表中的所有按钮,我们直接复制工作表,连按钮也会一起复制过来,需要把它们删除

总结

1、本文涉及了很多工作表的操作,比如,复制工作表,删除行、列,插入行,设置单元格的格式等。

2、像今天的案例,如果用数组来处理,就没有直接操作工作表来得方便了,因为数组插入、删除行列是非常麻烦的,没有工作表来得快。

3、如果数据量特别大,在数组里操作也是可行的。这里就不再展开。

---End---


相关推荐