【EXCEL】【VBA】根据行数据向右逐列填充求不均匀沉降

发布于:2025-02-11 ⋅ 阅读:(54) ⋅ 点赞:(0)
Sub CopyMaxAndMinRowsAndTranspose()
    Dim wsSource As Worksheet
    Dim wsTargetMax As Worksheet
    Dim wsTargetMin As Worksheet
    Dim lastRow As Long
    Dim i As Long, targetRowMax As Long, targetRowMin As Long
    Dim sourceData As Variant
    Dim maxRows() As Long, minRows() As Long
    Dim maxCount As Long, minCount As Long
    Dim startTime As Double
    
    startTime = Timer
    
    'Optimize Performance
    With Application
        .ScreenUpdating = False
        .EnableEvents = False
        .Calculation = xlCalculationManual
    End With
    
    'Set source worksheet
    Set wsSource = ThisWorkbook.Worksheets("03.Nodal Displacements(pileset)")
    
    'Check and create Max worksheet if it doesn't exist
    On Error Resume Next
    Set wsTargetMax = ThisWorkbook.Worksheets("03.diff. sett.(Max)")
    If wsTargetMax Is Nothing Then
        Set wsTargetMax = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
        wsTargetMax.Name = "03.diff. sett.(Max)"
    End If
    
    'Check and create Min worksheet if it doesn't exist
    Set wsTargetMin = ThisWorkbook.Worksheets("03.diff. sett.(Min)")
    If wsTargetMin Is Nothing Then
        Set wsTargetMin = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
        wsTargetMin.Name = "03.diff. sett.(Min)"
    End If
    On Error GoTo 0
    
    'Clear target worksheets content
    wsTargetMax.Cells.Clear
    wsTargetMin.Cells.Clear
    
    'Get last row and load data into array
    lastRow = wsSource.Cells(wsSource.Rows.Count, "A").End(xlUp).Row
    sourceData = wsSource.Range(wsSource.Cells(1, 1), wsSource.Cells(lastRow, wsSource.Cells(1, Columns.Count).End(xlToLeft).Column)).Value
    
    'Initialize arrays
    ReDim maxRows(1 To lastRow)
    ReDim minRows(1 To lastRow)
    maxCount = 0
    minCount = 0
    
    'Find all MAX and MIN rows
    For i = 4 To UBound(sourceData, 1)
        If UCase(Trim(CStr(sourceData(i, 1)))) = "MAX" Then
            maxCount = maxCount + 1
            maxRows(maxCount) = i
        ElseIf UCase(Trim(CStr(sourceData(i, 1)))) = "MIN" Then
            minCount = minCount + 1
            minRows(minCount) = i
        End If
    Next i
    
    'Resize arrays to actual size
    ReDim Preserve maxRows(1 To maxCount)
    ReDim Preserve minRows(1 To minCount)
    
    'Copy header rows (1-3)
    wsSource.Rows("1:3").Copy wsTargetMax.Rows("1")
    wsSource.Rows("1:3").Copy wsTargetMin.Rows("1")
    
    'Copy MAX rows in one operation
    If maxCount > 0 Then
        Dim maxRange As Range
        Set maxRange = wsSource.Rows(maxRows(1))
        For i = 2 To maxCount
            Set maxRange = Union(maxRange, wsSource.Rows(maxRows(i)))
        Next i
        maxRange.Copy wsTargetMax.Rows(4)
    End If
    
    'Copy MIN rows in one operation
    If minCount > 0 Then
        Dim minRange As Range
        Set minRange = wsSource.Rows(minRows(1))
        For i = 2 To minCount
            Set minRange = Union(minRange, wsSource.Rows(minRows(i)))
        Next i
        minRange.Copy wsTargetMin.Rows(4)
    End If
    


'处理Max sheet的转置
    If maxCount > 0 Then
        Dim maxDataArr As Variant
        maxDataArr = wsTargetMax.Range("C4:C" & (maxCount + 3)).Value
        
        'Transfer max data to horizontal array
        Dim maxTargetArr() As Variant
        ReDim maxTargetArr(1 To 1, 1 To UBound(maxDataArr, 1))
        For i = 1 To UBound(maxDataArr, 1)
            maxTargetArr(1, i) = maxDataArr(i, 1)
        Next i
        
        'Write max array horizontally
        wsTargetMax.Range("M3").Resize(1, UBound(maxDataArr, 1)) = maxTargetArr
        
        '添加公式并向下填充
        With wsTargetMax
            Dim lastRowMax As Long
            lastRowMax = .Cells(.Rows.Count, "C").End(xlUp).Row
            
            For i = 1 To UBound(maxDataArr, 1)
                '获取列字母
                Dim colLetter As String
                colLetter = Split(.Cells(1, i + 12).Address, "$")(1)
                
                '先写入第4行的公式
                .Cells(4, i + 12).Formula = "=ABS(VLOOKUP(TRIM($C4),$C:$H,6,FALSE)-VLOOKUP(TRIM(" & colLetter & "$3),$C:$H,6,FALSE))/'03.Obj Geom - Point Coordinates'!G4"
                
                '将公式向下填充到最后一行
                .Range(.Cells(4, i + 12), .Cells(lastRowMax, i + 12)).FillDown
            Next i
        End With
    End If
    
    '处理Min sheet的转置
    If minCount > 0 Then
        Dim minDataArr As Variant
        minDataArr = wsTargetMin.Range("C4:C" & (minCount + 3)).Value
        
        'Transfer min data to horizontal array
        Dim minTargetArr() As Variant
        ReDim minTargetArr(1 To 1, 1 To UBound(minDataArr, 1))
        For i = 1 To UBound(minDataArr, 1)
            minTargetArr(1, i) = minDataArr(i, 1)
        Next i
        
        'Write min array horizontally
        wsTargetMin.Range("M3").Resize(1, UBound(minDataArr, 1)) = minTargetArr
        
        '添加公式并向下填充
        With wsTargetMin
            Dim lastRowMin As Long
            lastRowMin = .Cells(.Rows.Count, "C").End(xlUp).Row
            
            For i = 1 To UBound(minDataArr, 1)
                '获取列字母
                colLetter = Split(.Cells(1, i + 12).Address, "$")(1)
                
                '先写入第4行的公式
                .Cells(4, i + 12).Formula = "=ABS(VLOOKUP(TRIM($C4),$C:$H,6,FALSE)-VLOOKUP(TRIM(" & colLetter & "$3),$C:$H,6,FALSE))/'03.Obj Geom - Point Coordinates'!G4"
                
                '将公式向下填充到最后一行
                .Range(.Cells(4, i + 12), .Cells(lastRowMin, i + 12)).FillDown
            Next i
        End With
    End If
    'Format the worksheets
    wsTargetMax.Columns.AutoFit
    wsTargetMin.Columns.AutoFit
    
    'Restore settings
    With Application
        .ScreenUpdating = True
        .EnableEvents = True
        .Calculation = xlCalculationAutomatic
        .CutCopyMode = False
    End With
    
    Debug.Print "执行时间: " & Format(Timer - startTime, "0.00") & " 秒"
    MsgBox "数据处理完成!" & vbNewLine & _
           "Max行数: " & maxCount & vbNewLine & _
           "Min行数: " & minCount & vbNewLine & _
           "执行时间: " & Format(Timer - startTime, "0.00") & " 秒", vbInformation
End Sub


在这里插入图片描述

程序流程图

MIN处理流程
MAX处理流程
不存在
存在
提取MIN行数据
处理MIN数据
转置数据到水平方向
添加计算公式
向下填充公式
提取MAX行数据
处理MAX数据
转置数据到水平方向
添加计算公式
向下填充公式
开始
性能优化设置
设置源工作表
检查目标工作表是否存在
创建新工作表
清空目标工作表
数据初始化
查找MAX和MIN行
复制标题行
格式化工作表
恢复Excel设置
显示执行结果
结束

主要功能模块说明

1. 初始化设置

  • 关闭屏幕刷新
  • 禁用事件
  • 设置手动计算模式

2. 工作表处理

  • 检查并创建Max和Min工作表
  • 清空目标工作表内容

3. 数据提取

  • 读取源数据
  • 识别MAX和MIN行
  • 复制相关数据

4. 数据转置与计算

  • 水平转置数据
  • 添加计算公式:
=ABS(VLOOKUP(TRIM($C4),$C:$H,6,FALSE)-VLOOKUP(TRIM(列字母$3),$C:$H,6,FALSE))/'03.Obj Geom - Point Coordinates'!G4

5. 格式化和完成

  • 自动调整列宽
  • 恢复Excel设置
  • 显示执行统计信息

性能优化特点

  1. 使用数组处理数据
  2. 批量复制而非逐行复制
  3. 优化Excel设置提高运行速度
  4. 使用Union方法合并范围操作

执行结果展示

程序完成后会显示:

  • Max行数统计
  • Min行数统计
  • 执行时间(秒)

V20250106

Sub CopyMaxAndMinRowsAndTranspose()
    Dim wsSource As Worksheet
    Dim wsTargetMax As Worksheet
    Dim wsTargetMin As Worksheet
    Dim lastRow As Long
    Dim i As Long, targetRowMax As Long, targetRowMin As Long
    Dim sourceData As Variant
    Dim maxRows() As Long, minRows() As Long
    Dim maxCount As Long, minCount As Long
    Dim startTime As Double
    
    startTime = Timer
    
    'Optimize Performance
    With Application
        .ScreenUpdating = False
        .EnableEvents = False
        .Calculation = xlCalculationManual
    End With
    
    On Error Resume Next
    'Set source worksheet
    Set wsSource = ThisWorkbook.Worksheets("03.Nodal Displacements(pileset)")
    
    'Check and create Max worksheet if it doesn't exist
    Set wsTargetMax = ThisWorkbook.Worksheets("03.diff. sett.(Max)")
    If wsTargetMax Is Nothing Then
        Set wsTargetMax = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
        wsTargetMax.Name = "03.diff. sett.(Max)"
    End If
    
    'Check and create Min worksheet if it doesn't exist
    Set wsTargetMin = ThisWorkbook.Worksheets("03.diff. sett.(Min)")
    If wsTargetMin Is Nothing Then
        Set wsTargetMin = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
        wsTargetMin.Name = "03.diff. sett.(Min)"
    End If
    On Error GoTo 0
    
    'Clear target worksheets content
    wsTargetMax.Cells.Clear
    wsTargetMin.Cells.Clear
    
    'Get last row and load data into array
    lastRow = wsSource.Cells(wsSource.Rows.Count, "A").End(xlUp).Row
    sourceData = wsSource.Range(wsSource.Cells(1, 1), wsSource.Cells(lastRow, wsSource.Cells(1, Columns.Count).End(xlToLeft).Column)).Value
    
    'Initialize arrays
    ReDim maxRows(1 To lastRow)
    ReDim minRows(1 To lastRow)
    maxCount = 0
    minCount = 0
    
    'Find all MAX and MIN rows
    For i = 4 To UBound(sourceData, 1)
        If UCase(Trim(CStr(sourceData(i, 1)))) = "MAX" Then
            maxCount = maxCount + 1
            maxRows(maxCount) = i
        ElseIf UCase(Trim(CStr(sourceData(i, 1)))) = "MIN" Then
            minCount = minCount + 1
            minRows(minCount) = i
        End If
    Next i
    
    'Resize arrays to actual size
    ReDim Preserve maxRows(1 To maxCount)
    ReDim Preserve minRows(1 To minCount)
    
    'Copy header rows (1-3)
    wsSource.Rows("1:3").Copy wsTargetMax.Rows("1")
    wsSource.Rows("1:3").Copy wsTargetMin.Rows("1")
    
    'Copy MAX rows in one operation
    If maxCount > 0 Then
        Dim maxRange As Range
        Set maxRange = wsSource.Rows(maxRows(1))
        For i = 2 To maxCount
            Set maxRange = Union(maxRange, wsSource.Rows(maxRows(i)))
        Next i
        maxRange.Copy wsTargetMax.Rows(4)
    End If
    
    'Copy MIN rows in one operation
    If minCount > 0 Then
        Dim minRange As Range
        Set minRange = wsSource.Rows(minRows(1))
        For i = 2 To minCount
            Set minRange = Union(minRange, wsSource.Rows(minRows(i)))
        Next i
        minRange.Copy wsTargetMin.Rows(4)
    End If
    
    '处理Max sheet的转置
    If maxCount > 0 Then
        Dim maxDataArr As Variant
        maxDataArr = wsTargetMax.Range("C4:C" & (maxCount + 3)).Value
        
        'Transfer max data to horizontal array
        Dim maxTargetArr() As Variant
        ReDim maxTargetArr(1 To 1, 1 To UBound(maxDataArr, 1))
        For i = 1 To UBound(maxDataArr, 1)
            maxTargetArr(1, i) = maxDataArr(i, 1)
        Next i
        
        'Write max array horizontally
        wsTargetMax.Range("M3").Resize(1, UBound(maxDataArr, 1)) = maxTargetArr
        
        With wsTargetMax
            Dim lastRowMax As Long
            lastRowMax = .Cells(.Rows.Count, "C").End(xlUp).Row
            
            For i = 1 To UBound(maxDataArr, 1)
                Dim colLetter As String
                colLetter = Split(wsTargetMax.Cells(1, i + 12).Address, "$")(1)
                
                'Modified formula generation
                For j = 4 To lastRowMax
                    Dim refColumn As String
                    refColumn = Split(Cells(1, i + 6).Address, "$")(1) '从G列(7)开始,随i递增
                    
                    .Cells(j, i + 12).formula = "=IF('03.Obj Geom - Point Coordinates'!" & refColumn & j & "=0,0,ABS(VLOOKUP(TRIM($C" & j & "),$C:$H,6,FALSE)-VLOOKUP(TRIM(" & colLetter & "$3),$C:$H,6,FALSE))/'03.Obj Geom - Point Coordinates'!" & refColumn & j & ")"
                Next j
            Next i
            
            'Add conditional formatting for max values
            Dim maxDataRange As Range
            Set maxDataRange = .Range(.Cells(4, 13), .Cells(lastRowMax, 12 + UBound(maxDataArr, 1)))
            maxDataRange.FormatConditions.Delete
            
            With maxDataRange.FormatConditions.Add(Type:=xlCellValue, Operator:=xlGreater, Formula1:=0.002)
                .Interior.Color = RGB(255, 0, 0)
            End With
            
            'Add check formula in M1
            .Range("M1").formula = "=IF(MAX(M4:" & Split(.Cells(4, 12 + UBound(maxDataArr, 1)).Address, "$")(1) & lastRowMax & ")>0.002,""存在大于0.002的值"",""全部符合要求"")"
        End With
    End If
    
    '处理Min sheet的转置
    If minCount > 0 Then
        Dim minDataArr As Variant
        minDataArr = wsTargetMin.Range("C4:C" & (minCount + 3)).Value
        
        'Transfer min data to horizontal array
        Dim minTargetArr() As Variant
        ReDim minTargetArr(1 To 1, 1 To UBound(minDataArr, 1))
        For i = 1 To UBound(minDataArr, 1)
            minTargetArr(1, i) = minDataArr(i, 1)
        Next i
        
        'Write min array horizontally
        wsTargetMin.Range("M3").Resize(1, UBound(minDataArr, 1)) = minTargetArr
        
        With wsTargetMin
            Dim lastRowMin As Long
            lastRowMin = .Cells(.Rows.Count, "C").End(xlUp).Row
            
            For i = 1 To UBound(minDataArr, 1)
                colLetter = Split(wsTargetMin.Cells(1, i + 12).Address, "$")(1)
                
                'Modified formula generation
                For j = 4 To lastRowMin
                    refColumn = Split(Cells(1, i + 6).Address, "$")(1) '从G列(7)开始,随i递增
                    
                    .Cells(j, i + 12).formula = "=IF('03.Obj Geom - Point Coordinates'!" & refColumn & j & "=0,0,ABS(VLOOKUP(TRIM($C" & j & "),$C:$H,6,FALSE)-VLOOKUP(TRIM(" & colLetter & "$3),$C:$H,6,FALSE))/'03.Obj Geom - Point Coordinates'!" & refColumn & j & ")"
                Next j
            Next i
            
            'Add conditional formatting for min values
            Dim minDataRange As Range
            Set minDataRange = .Range(.Cells(4, 13), .Cells(lastRowMin, 12 + UBound(minDataArr, 1)))
            minDataRange.FormatConditions.Delete
            
            With minDataRange.FormatConditions.Add(Type:=xlCellValue, Operator:=xlGreater, Formula1:=0.002)
                .Interior.Color = RGB(255, 0, 0)
            End With
            
            'Add check formula in M1
            .Range("M1").formula = "=IF(MAX(M4:" & Split(.Cells(4, 12 + UBound(minDataArr, 1)).Address, "$")(1) & lastRowMin & ")>0.002,""存在大于0.002的值"",""全部符合要求"")"
        End With
    End If
    
    'Format the worksheets
    wsTargetMax.Columns.AutoFit
    wsTargetMin.Columns.AutoFit
    
    'Restore settings
    With Application
        .ScreenUpdating = True
        .EnableEvents = True
        .Calculation = xlCalculationAutomatic
        .CutCopyMode = False
    End With
    
    Debug.Print "执行时间: " & Format(Timer - startTime, "0.00") & " 秒"
    MsgBox "数据处理完成!" & vbNewLine & _
           "Max行数: " & maxCount & vbNewLine & _
           "Min行数: " & minCount & vbNewLine & _
           "执行时间: " & Format(Timer - startTime, "0.00") & " 秒", vbInformation
End Sub

V20250106 English reminder

Sub CopyMaxAndMinRowsAndTranspose()
    Dim wsSource As Worksheet
    Dim wsTargetMax As Worksheet
    Dim wsTargetMin As Worksheet
    Dim lastRow As Long
    Dim i As Long, targetRowMax As Long, targetRowMin As Long
    Dim sourceData As Variant
    Dim maxRows() As Long, minRows() As Long
    Dim maxCount As Long, minCount As Long
    Dim startTime As Double
    
    startTime = Timer
    
    'Optimize Performance
    With Application
        .ScreenUpdating = False
        .EnableEvents = False
        .Calculation = xlCalculationManual
    End With
    
    On Error Resume Next
    'Set source worksheet
    Set wsSource = ThisWorkbook.Worksheets("03.Nodal Displacements(pileset)")
    
    'Check and create Max worksheet if it doesn't exist
    Set wsTargetMax = ThisWorkbook.Worksheets("03.diff. sett.(Max)")
    If wsTargetMax Is Nothing Then
        Set wsTargetMax = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
        wsTargetMax.Name = "03.diff. sett.(Max)"
    End If
    
    'Check and create Min worksheet if it doesn't exist
    Set wsTargetMin = ThisWorkbook.Worksheets("03.diff. sett.(Min)")
    If wsTargetMin Is Nothing Then
        Set wsTargetMin = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
        wsTargetMin.Name = "03.diff. sett.(Min)"
    End If
    On Error GoTo 0
    
    'Clear target worksheets content
    wsTargetMax.Cells.Clear
    wsTargetMin.Cells.Clear
    
    'Get last row and load data into array
    lastRow = wsSource.Cells(wsSource.Rows.Count, "A").End(xlUp).Row
    sourceData = wsSource.Range(wsSource.Cells(1, 1), wsSource.Cells(lastRow, wsSource.Cells(1, Columns.Count).End(xlToLeft).Column)).Value
    
    'Initialize arrays
    ReDim maxRows(1 To lastRow)
    ReDim minRows(1 To lastRow)
    maxCount = 0
    minCount = 0
    
    'Find all MAX and MIN rows
    For i = 4 To UBound(sourceData, 1)
        If UCase(Trim(CStr(sourceData(i, 1)))) = "MAX" Then
            maxCount = maxCount + 1
            maxRows(maxCount) = i
        ElseIf UCase(Trim(CStr(sourceData(i, 1)))) = "MIN" Then
            minCount = minCount + 1
            minRows(minCount) = i
        End If
    Next i
    
    'Resize arrays to actual size
    ReDim Preserve maxRows(1 To maxCount)
    ReDim Preserve minRows(1 To minCount)
    
    'Copy header rows (1-3)
    wsSource.Rows("1:3").Copy wsTargetMax.Rows("1")
    wsSource.Rows("1:3").Copy wsTargetMin.Rows("1")
    
    'Copy MAX rows in one operation
    If maxCount > 0 Then
        Dim maxRange As Range
        Set maxRange = wsSource.Rows(maxRows(1))
        For i = 2 To maxCount
            Set maxRange = Union(maxRange, wsSource.Rows(maxRows(i)))
        Next i
        maxRange.Copy wsTargetMax.Rows(4)
    End If
    
    'Copy MIN rows in one operation
    If minCount > 0 Then
        Dim minRange As Range
        Set minRange = wsSource.Rows(minRows(1))
        For i = 2 To minCount
            Set minRange = Union(minRange, wsSource.Rows(minRows(i)))
        Next i
        minRange.Copy wsTargetMin.Rows(4)
    End If
    
    '处理Max sheet的转置
    If maxCount > 0 Then
        Dim maxDataArr As Variant
        maxDataArr = wsTargetMax.Range("C4:C" & (maxCount + 3)).Value
        
        'Transfer max data to horizontal array
        Dim maxTargetArr() As Variant
        ReDim maxTargetArr(1 To 1, 1 To UBound(maxDataArr, 1))
        For i = 1 To UBound(maxDataArr, 1)
            maxTargetArr(1, i) = maxDataArr(i, 1)
        Next i
        
        'Write max array horizontally
        wsTargetMax.Range("M3").Resize(1, UBound(maxDataArr, 1)) = maxTargetArr
        
        With wsTargetMax
            Dim lastRowMax As Long
            lastRowMax = .Cells(.Rows.Count, "C").End(xlUp).Row
            
            For i = 1 To UBound(maxDataArr, 1)
                Dim colLetter As String
                colLetter = Split(wsTargetMax.Cells(1, i + 12).Address, "$")(1)
                
                For j = 4 To lastRowMax
                    Dim refColumn As String
                    refColumn = Split(Cells(1, i + 6).Address, "$")(1)
                    
                    .Cells(j, i + 12).formula = "=ROUND(IF('03.Obj Geom - Point Coordinates'!" & refColumn & j & "=0,0,ABS(VLOOKUP(TRIM($C" & j & "),$C:$H,6,FALSE)-VLOOKUP(TRIM(" & colLetter & "$3),$C:$H,6,FALSE))/'03.Obj Geom - Point Coordinates'!" & refColumn & j & "),4)"
                    .Cells(j, i + 12).NumberFormat = "0.0000"
                Next j
            Next i
            
            'Add conditional formatting for max values
            Dim maxDataRange As Range
            Set maxDataRange = .Range(.Cells(4, 13), .Cells(lastRowMax, 12 + UBound(maxDataArr, 1)))
            maxDataRange.FormatConditions.Delete
            
            With maxDataRange.FormatConditions.Add(Type:=xlCellValue, Operator:=xlGreater, Formula1:=0.002)
                .Interior.Color = RGB(255, 0, 0)
            End With
            
            'Add check formula in M1
            .Range("M1").formula = "=IF(MAX(M4:" & Split(.Cells(4, 12 + UBound(maxDataArr, 1)).Address, "$")(1) & lastRowMax & ")>0.002,""Values > 0.002 exist"",""All values within limits"")"
        End With
    End If
    
    '处理Min sheet的转置
    If minCount > 0 Then
        Dim minDataArr As Variant
        minDataArr = wsTargetMin.Range("C4:C" & (minCount + 3)).Value
        
        'Transfer min data to horizontal array
        Dim minTargetArr() As Variant
        ReDim minTargetArr(1 To 1, 1 To UBound(minDataArr, 1))
        For i = 1 To UBound(minDataArr, 1)
            minTargetArr(1, i) = minDataArr(i, 1)
        Next i
        
        'Write min array horizontally
        wsTargetMin.Range("M3").Resize(1, UBound(minDataArr, 1)) = minTargetArr
        
        With wsTargetMin
            Dim lastRowMin As Long
            lastRowMin = .Cells(.Rows.Count, "C").End(xlUp).Row
            
            For i = 1 To UBound(minDataArr, 1)
                colLetter = Split(wsTargetMin.Cells(1, i + 12).Address, "$")(1)
                
                For j = 4 To lastRowMin
                    refColumn = Split(Cells(1, i + 6).Address, "$")(1)
                    
                    .Cells(j, i + 12).formula = "=ROUND(IF('03.Obj Geom - Point Coordinates'!" & refColumn & j & "=0,0,ABS(VLOOKUP(TRIM($C" & j & "),$C:$H,6,FALSE)-VLOOKUP(TRIM(" & colLetter & "$3),$C:$H,6,FALSE))/'03.Obj Geom - Point Coordinates'!" & refColumn & j & "),4)"
                    .Cells(j, i + 12).NumberFormat = "0.0000"
                Next j
            Next i
            
            'Add conditional formatting for min values
            Dim minDataRange As Range
            Set minDataRange = .Range(.Cells(4, 13), .Cells(lastRowMin, 12 + UBound(minDataArr, 1)))
            minDataRange.FormatConditions.Delete
            
            With minDataRange.FormatConditions.Add(Type:=xlCellValue, Operator:=xlGreater, Formula1:=0.002)
                .Interior.Color = RGB(255, 0, 0)
            End With
            
            'Add check formula in M1
            .Range("M1").formula = "=IF(MAX(M4:" & Split(.Cells(4, 12 + UBound(minDataArr, 1)).Address, "$")(1) & lastRowMin & ")>0.002,""Values > 0.002 exist"",""All values within limits"")"
        End With
    End If
    
    'Format the worksheets
    wsTargetMax.Columns.AutoFit
    wsTargetMin.Columns.AutoFit
    
    'Restore settings
    With Application
        .ScreenUpdating = True
        .EnableEvents = True
        .Calculation = xlCalculationAutomatic
        .CutCopyMode = False
    End With
    
    Debug.Print "Execution time: " & Format(Timer - startTime, "0.00") & " seconds"
    MsgBox "Data processing completed!" & vbNewLine & _
           "Max rows: " & maxCount & vbNewLine & _
           "Min rows: " & minCount & vbNewLine & _
           "Execution time: " & Format(Timer - startTime, "0.00") & " seconds", vbInformation
End Sub


V20250109 verify text formation

update note

  • 在设置值之前,先将整个区域设置为文本格式 (.NumberFormat = “@”)
  • 在设置每个单元格的值时,使用单引号强制文本格式 (“'” & CStr(dataArr(i, 1)))
  • 使用CStr函数确保数值转换为文本
Sub DifferentialSettlementUpdate()
    Dim wsSource As Worksheet
    Dim wsTargetMax As Worksheet
    Dim wsTargetMin As Worksheet
    Dim lastRow As Long
    Dim i As Long, targetRowMax As Long, targetRowMin As Long
    Dim sourceData As Variant
    Dim maxRows() As Long, minRows() As Long
    Dim maxCount As Long, minCount As Long
    Dim startTime As Double
    
    startTime = Timer
    
    With Application
        .ScreenUpdating = False
        .EnableEvents = False
        .Calculation = xlCalculationManual
    End With
    
    On Error Resume Next
    Set wsSource = ThisWorkbook.Worksheets("03.Nodal Displacements(pileset)")
    
    Set wsTargetMax = ThisWorkbook.Worksheets("03.diff. sett.(Max)")
    If wsTargetMax Is Nothing Then
        Set wsTargetMax = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
        wsTargetMax.Name = "03.diff. sett.(Max)"
    End If
    
    Set wsTargetMin = ThisWorkbook.Worksheets("03.diff. sett.(Min)")
    If wsTargetMin Is Nothing Then
        Set wsTargetMin = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
        wsTargetMin.Name = "03.diff. sett.(Min)"
    End If
    On Error GoTo 0
    
    wsTargetMax.Cells.Clear
    wsTargetMin.Cells.Clear
    
    lastRow = wsSource.Cells(wsSource.Rows.Count, "A").End(xlUp).Row
    sourceData = wsSource.Range(wsSource.Cells(1, 1), wsSource.Cells(lastRow, wsSource.Cells(1, Columns.Count).End(xlToLeft).Column)).Value
    
    ReDim maxRows(1 To lastRow)
    ReDim minRows(1 To lastRow)
    maxCount = 0
    minCount = 0
    
    For i = 4 To UBound(sourceData, 1)
        If UCase(Trim(CStr(sourceData(i, 1)))) = "MAX" Then
            maxCount = maxCount + 1
            maxRows(maxCount) = i
        ElseIf UCase(Trim(CStr(sourceData(i, 1)))) = "MIN" Then
            minCount = minCount + 1
            minRows(minCount) = i
        End If
    Next i
    
    ReDim Preserve maxRows(1 To maxCount)
    ReDim Preserve minRows(1 To minCount)
    
    wsSource.Rows("1:3").Copy wsTargetMax.Rows("1")
    wsSource.Rows("1:3").Copy wsTargetMin.Rows("1")
    
    ' 设置目标工作表的格式为文本
    wsTargetMax.Range("M3").Resize(1, maxCount).NumberFormat = "@"
    wsTargetMin.Range("M3").Resize(1, minCount).NumberFormat = "@"
    
    If maxCount > 0 Then
        Dim maxRange As Range
        Set maxRange = wsSource.Rows(maxRows(1))
        For i = 2 To maxCount
            Set maxRange = Union(maxRange, wsSource.Rows(maxRows(i)))
        Next i
        maxRange.Copy wsTargetMax.Rows(4)
    End If
    
    If minCount > 0 Then
        Dim minRange As Range
        Set minRange = wsSource.Rows(minRows(1))
        For i = 2 To minCount
            Set minRange = Union(minRange, wsSource.Rows(minRows(i)))
        Next i
        minRange.Copy wsTargetMin.Rows(4)
    End If
    
    If maxCount > 0 Then
        Dim maxDataArr As Variant
        maxDataArr = wsTargetMax.Range("C4:C" & (maxCount + 3)).Value
        
        Dim maxTargetArr() As Variant
        ReDim maxTargetArr(1 To 1, 1 To UBound(maxDataArr, 1))
        For i = 1 To UBound(maxDataArr, 1)
            ' 添加单引号确保文本格式
            maxTargetArr(1, i) = "'" & CStr(maxDataArr(i, 1))
        Next i
        
        wsTargetMax.Range("M3").Resize(1, UBound(maxDataArr, 1)) = maxTargetArr
        
        With wsTargetMax
            Dim lastRowMax As Long
            lastRowMax = .Cells(.Rows.Count, "C").End(xlUp).Row
            
            For i = 1 To UBound(maxDataArr, 1)
                Dim colLetter As String
                colLetter = Split(wsTargetMax.Cells(1, i + 12).Address, "$")(1)
                
                For j = 4 To lastRowMax
                    Dim refColumn As String
                    refColumn = Split(Cells(1, i + 6).Address, "$")(1)
                    
                    .Cells(j, i + 12).Formula = "=ROUND(IF('03.Obj Geom - Point Coordinates'!" & refColumn & j & "=0,0,ABS(VLOOKUP(TRIM($C" & j & "),$C:$H,6,FALSE)-VLOOKUP(TRIM(" & colLetter & "$3),$C:$H,6,FALSE))/'03.Obj Geom - Point Coordinates'!" & refColumn & j & "),4)"
                    .Cells(j, i + 12).NumberFormat = "0.0000"
                Next j
            Next i
            
            Dim maxDataRange As Range
            Set maxDataRange = .Range(.Cells(4, 13), .Cells(lastRowMax, 12 + UBound(maxDataArr, 1)))
            maxDataRange.FormatConditions.Delete
            
            With maxDataRange.FormatConditions.Add(Type:=xlCellValue, Operator:=xlGreater, Formula1:=0.002)
                .Interior.Color = RGB(255, 0, 0)
            End With
            
            .Range("M1").Formula = "=IF(MAX(M4:" & Split(.Cells(4, 12 + UBound(maxDataArr, 1)).Address, "$")(1) & lastRowMax & ")>0.002,""Values > 0.002 exist"",""All values within limits"")"
        End With
    End If
    
    If minCount > 0 Then
        Dim minDataArr As Variant
        minDataArr = wsTargetMin.Range("C4:C" & (minCount + 3)).Value
        
        Dim minTargetArr() As Variant
        ReDim minTargetArr(1 To 1, 1 To UBound(minDataArr, 1))
        For i = 1 To UBound(minDataArr, 1)
            ' 添加单引号确保文本格式
            minTargetArr(1, i) = "'" & CStr(minDataArr(i, 1))
        Next i
        
        wsTargetMin.Range("M3").Resize(1, UBound(minDataArr, 1)) = minTargetArr
        
        With wsTargetMin
            Dim lastRowMin As Long
            lastRowMin = .Cells(.Rows.Count, "C").End(xlUp).Row
            
            For i = 1 To UBound(minDataArr, 1)
                colLetter = Split(wsTargetMin.Cells(1, i + 12).Address, "$")(1)
                
                For j = 4 To lastRowMin
                    refColumn = Split(Cells(1, i + 6).Address, "$")(1)
                    
                    .Cells(j, i + 12).Formula = "=ROUND(IF('03.Obj Geom - Point Coordinates'!" & refColumn & j & "=0,0,ABS(VLOOKUP(TRIM($C" & j & "),$C:$H,6,FALSE)-VLOOKUP(TRIM(" & colLetter & "$3),$C:$H,6,FALSE))/'03.Obj Geom - Point Coordinates'!" & refColumn & j & "),4)"
                    .Cells(j, i + 12).NumberFormat = "0.0000"
                Next j
            Next i
            
            Dim minDataRange As Range
            Set minDataRange = .Range(.Cells(4, 13), .Cells(lastRowMin, 12 + UBound(minDataArr, 1)))
            minDataRange.FormatConditions.Delete
            
            With minDataRange.FormatConditions.Add(Type:=xlCellValue, Operator:=xlGreater, Formula1:=0.002)
                .Interior.Color = RGB(255, 0, 0)
            End With
            
            .Range("M1").Formula = "=IF(MAX(M4:" & Split(.Cells(4, 12 + UBound(minDataArr, 1)).Address, "$")(1) & lastRowMin & ")>0.002,""Values > 0.002 exist"",""All values within limits"")"
        End With
    End If
    
    wsTargetMax.Columns.AutoFit
    wsTargetMin.Columns.AutoFit
    
    With Application
        .ScreenUpdating = True
        .EnableEvents = True
        .Calculation = xlCalculationAutomatic
        .CutCopyMode = False
    End With
    
    Debug.Print "Execution time: " & Format(Timer - startTime, "0.00") & " seconds"
    MsgBox "Data processing completed!" & vbNewLine & _
           "Max rows: " & maxCount & vbNewLine & _
           "Min rows: " & minCount & vbNewLine & _
           "Execution time: " & Format(Timer - startTime, "0.00") & " seconds", vbInformation
End Sub


V20250109 inner formula directly cite coordination and calculate distance

  • sometimes , if distance table and settlement table not absolutely map, may led result wrong, so just use one formula to calculate settlement ,and distance table just for reference.
Sub DifferentialSettlementUpdate()
    Dim wsSource As Worksheet
    Dim wsTargetMax As Worksheet
    Dim wsTargetMin As Worksheet
    Dim lastRow As Long
    Dim i As Long, targetRowMax As Long, targetRowMin As Long
    Dim sourceData As Variant
    Dim maxRows() As Long, minRows() As Long
    Dim maxCount As Long, minCount As Long
    Dim startTime As Double
    
    startTime = Timer
    
    With Application
        .ScreenUpdating = False
        .EnableEvents = False
        .Calculation = xlCalculationManual
    End With
    
    On Error Resume Next
    Set wsSource = ThisWorkbook.Worksheets("03.Nodal Displacements(pileset)")
    
    Set wsTargetMax = ThisWorkbook.Worksheets("03.diff. sett.(Max)")
    If wsTargetMax Is Nothing Then
        Set wsTargetMax = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.sheets(ThisWorkbook.sheets.Count))
        wsTargetMax.Name = "03.diff. sett.(Max)"
    End If
    
    Set wsTargetMin = ThisWorkbook.Worksheets("03.diff. sett.(Min)")
    If wsTargetMin Is Nothing Then
        Set wsTargetMin = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.sheets(ThisWorkbook.sheets.Count))
        wsTargetMin.Name = "03.diff. sett.(Min)"
    End If
    On Error GoTo 0
    
    wsTargetMax.Cells.Clear
    wsTargetMin.Cells.Clear
    
    lastRow = wsSource.Cells(wsSource.Rows.Count, "A").End(xlUp).row
    sourceData = wsSource.Range(wsSource.Cells(1, 1), wsSource.Cells(lastRow, wsSource.Cells(1, Columns.Count).End(xlToLeft).Column)).Value
    
    ReDim maxRows(1 To lastRow)
    ReDim minRows(1 To lastRow)
    maxCount = 0
    minCount = 0
    
    For i = 4 To UBound(sourceData, 1)
        If UCase(Trim(CStr(sourceData(i, 1)))) = "MAX" Then
            maxCount = maxCount + 1
            maxRows(maxCount) = i
        ElseIf UCase(Trim(CStr(sourceData(i, 1)))) = "MIN" Then
            minCount = minCount + 1
            minRows(minCount) = i
        End If
    Next i
    
    ReDim Preserve maxRows(1 To maxCount)
    ReDim Preserve minRows(1 To minCount)
    
    wsSource.Rows("1:3").Copy wsTargetMax.Rows("1")
    wsSource.Rows("1:3").Copy wsTargetMin.Rows("1")
    
    wsTargetMax.Range("M3").Resize(1, maxCount).NumberFormat = "@"
    wsTargetMin.Range("M3").Resize(1, minCount).NumberFormat = "@"
    
    If maxCount > 0 Then
        Dim maxRange As Range
        Set maxRange = wsSource.Rows(maxRows(1))
        For i = 2 To maxCount
            Set maxRange = Union(maxRange, wsSource.Rows(maxRows(i)))
        Next i
        maxRange.Copy wsTargetMax.Rows(4)
    End If
    
    If minCount > 0 Then
        Dim minRange As Range
        Set minRange = wsSource.Rows(minRows(1))
        For i = 2 To minCount
            Set minRange = Union(minRange, wsSource.Rows(minRows(i)))
        Next i
        minRange.Copy wsTargetMin.Rows(4)
    End If
    
    If maxCount > 0 Then
        Dim maxDataArr As Variant
        maxDataArr = wsTargetMax.Range("C4:C" & (maxCount + 3)).Value
        
        Dim maxTargetArr() As Variant
        ReDim maxTargetArr(1 To 1, 1 To UBound(maxDataArr, 1))
        For i = 1 To UBound(maxDataArr, 1)
            maxTargetArr(1, i) = "'" & CStr(maxDataArr(i, 1))
        Next i
        
        wsTargetMax.Range("M3").Resize(1, UBound(maxDataArr, 1)) = maxTargetArr
        
        With wsTargetMax
            Dim lastRowMax As Long
            lastRowMax = .Cells(.Rows.Count, "C").End(xlUp).row
            
            For i = 1 To UBound(maxDataArr, 1)
                Dim colLetter As String
                colLetter = Split(wsTargetMax.Cells(1, i + 12).Address, "$")(1)
                
                For j = 4 To lastRowMax
                    .Cells(j, i + 12).Formula = "=IFERROR(ROUND(ABS(VLOOKUP(TRIM($C" & j & "),$C:$H,6,FALSE)-VLOOKUP(TRIM(" & colLetter & "$3),$C:$H,6,FALSE))/(SQRT((VLOOKUP($C" & j & ",'03.Obj Geom - Point Coordinates'!$A:$E,2,FALSE)-VLOOKUP(" & colLetter & "$3,'03.Obj Geom - Point Coordinates'!$A:$E,2,FALSE))^2+(VLOOKUP($C" & j & ",'03.Obj Geom - Point Coordinates'!$A:$E,3,FALSE)-VLOOKUP(" & colLetter & "$3,'03.Obj Geom - Point Coordinates'!$A:$E,3,FALSE))^2))/1000,4),"""")"
                    .Cells(j, i + 12).NumberFormat = "0.0000"
                Next j
            Next i
            
            Dim maxDataRange As Range
            Set maxDataRange = .Range(.Cells(4, 13), .Cells(lastRowMax, 12 + UBound(maxDataArr, 1)))
            maxDataRange.FormatConditions.Delete
            
            With maxDataRange.FormatConditions.Add(Type:=xlCellValue, Operator:=xlGreater, Formula1:=0.002)
                .Interior.Color = RGB(255, 0, 0)
            End With
            
            With maxDataRange.FormatConditions.Add(Type:=xlCellValue, Operator:=xlEqual, Formula1:="""""")
                .Interior.Color = RGB(192, 192, 192)
            End With
            
            .Range("M1").Formula = "=IF(MAX(M4:" & Split(.Cells(4, 12 + UBound(maxDataArr, 1)).Address, "$")(1) & lastRowMax & ")>0.002,""Values > 0.002 exist"",""All values within limits"")"
        End With
    End If
    
    If minCount > 0 Then
        Dim minDataArr As Variant
        minDataArr = wsTargetMin.Range("C4:C" & (minCount + 3)).Value
        
        Dim minTargetArr() As Variant
        ReDim minTargetArr(1 To 1, 1 To UBound(minDataArr, 1))
        For i = 1 To UBound(minDataArr, 1)
            minTargetArr(1, i) = "'" & CStr(minDataArr(i, 1))
        Next i
        
        wsTargetMin.Range("M3").Resize(1, UBound(minDataArr, 1)) = minTargetArr
        
        With wsTargetMin
            Dim lastRowMin As Long
            lastRowMin = .Cells(.Rows.Count, "C").End(xlUp).row
            
            For i = 1 To UBound(minDataArr, 1)
                colLetter = Split(wsTargetMin.Cells(1, i + 12).Address, "$")(1)
                
                For j = 4 To lastRowMin
                    .Cells(j, i + 12).Formula = "=IFERROR(ROUND(ABS(VLOOKUP(TRIM($C" & j & "),$C:$H,6,FALSE)-VLOOKUP(TRIM(" & colLetter & "$3),$C:$H,6,FALSE))/(SQRT((VLOOKUP($C" & j & ",'03.Obj Geom - Point Coordinates'!$A:$E,2,FALSE)-VLOOKUP(" & colLetter & "$3,'03.Obj Geom - Point Coordinates'!$A:$E,2,FALSE))^2+(VLOOKUP($C" & j & ",'03.Obj Geom - Point Coordinates'!$A:$E,3,FALSE)-VLOOKUP(" & colLetter & "$3,'03.Obj Geom - Point Coordinates'!$A:$E,3,FALSE))^2))/1000,4),"""")"
                    .Cells(j, i + 12).NumberFormat = "0.0000"
                Next j
            Next i
            
            Dim minDataRange As Range
            Set minDataRange = .Range(.Cells(4, 13), .Cells(lastRowMin, 12 + UBound(minDataArr, 1)))
            minDataRange.FormatConditions.Delete
            
            With minDataRange.FormatConditions.Add(Type:=xlCellValue, Operator:=xlGreater, Formula1:=0.002)
                .Interior.Color = RGB(255, 0, 0)
            End With
            
            With minDataRange.FormatConditions.Add(Type:=xlCellValue, Operator:=xlEqual, Formula1:="""""")
                .Interior.Color = RGB(192, 192, 192)
            End With
            
            .Range("M1").Formula = "=IF(MAX(M4:" & Split(.Cells(4, 12 + UBound(minDataArr, 1)).Address, "$")(1) & lastRowMin & ")>0.002,""Values > 0.002 exist"",""All values within limits"")"
        End With
    End If
    
    wsTargetMax.Columns.AutoFit
    wsTargetMin.Columns.AutoFit
    
    With Application
        .ScreenUpdating = True
        .EnableEvents = True
        .Calculation = xlCalculationAutomatic
        .CutCopyMode = False
    End With
    
    Debug.Print "Execution time: " & Format(Timer - startTime, "0.00") & " seconds"
    MsgBox "Data processing completed!" & vbNewLine & _
           "Max rows: " & maxCount & vbNewLine & _
           "Min rows: " & minCount & vbNewLine & _
           "Execution time: " & Format(Timer - startTime, "0.00") & " seconds", vbInformation
End Sub



网站公告

今日签到

点亮在社区的每一天
去签到