【Excel】【VBA】Reaction超限点筛选与散点图可视化

【Excel】【VBA】Reaction超限点筛选与散点图可视化

功能概述

这段代码实现了以下功能:

  1. 从SAFE输出的结果worksheet通过datalink获取更新数据
  2. 从指定工作表中读取数据
  3. 检测超过阈值的数据点
  4. 生成结果表格并添加格式化
  5. 创建可视化散点图
  6. 显示执行时间

流程图

初始化 是 否 开始 读取数据 检测超限值 是否有超限点? 创建结果表格 添加格式化 创建散点图 恢复Excel设置 显示执行时间 结束

关键方法详解

1. 性能优化技巧

vba 复制代码
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
  • 禁用屏幕更新和自动计算,提高执行效率
  • 完成后需要恢复这些设置

2. 数组操作

vba 复制代码
dataArray = .Range(.Cells(1, 1), .Cells(lastRow, 10)).Value
ReDim Preserve results(1 To 10, 1 To itemCount)
  • 使用数组批量读取数据,比逐单元格读取更快
  • ReDim Preserve 允许动态调整数组大小同时保留现有数据

3. 错误处理

vba 复制代码
On Error Resume Next
' 代码块
On Error GoTo 0
  • 使用错误处理确保代码稳定性
  • 可以优雅地处理工作表不存在等异常情况

4. 条件格式化

vba 复制代码
formatRange.FormatConditions.AddDatabar
With formatRange.FormatConditions(1)
    .BarFillType = xlDataBarFillSolid
    .BarColor.Color = RGB(255, 0, 0)
End With
  • 添加数据条来可视化超限比率
  • 使用RGB颜色定义来设置格式

5. 图表创建

vba 复制代码
Set chtObj = wsResult.ChartObjects.Add(...)
With chtObj.Chart
    .ChartType = xlXYScatter
    .SeriesCollection.NewSeries
    ' 设置数据源和格式
End With
  • 使用ChartObjects创建图表对象
  • 设置图表类型、数据源和格式化选项

6. 数据标签

vba 复制代码
With .DataLabels
    .ShowValue = False
    .Format.TextFrame2.TextRange.Font.Size = 8
    For pt = 1 To .Count
        .Item(pt).Text = Format(wsResult.Cells(pt + 1, "M").Value, "0.00%")
    Next pt
End With
  • 为散点添加自定义数据标签
  • 使用Format函数格式化百分比显示

学习要点

  1. 数据处理效率

    • 使用数组批量处理数据
    • 禁用不必要的Excel功能提升性能
  2. 代码结构

    • 使用With语句块简化代码
    • 合理组织代码逻辑,提高可读性
  3. 错误处理

    • 在关键操作处添加错误处理
    • 确保程序稳定运行
  4. Excel对象模型

    • 理解工作表、单元格范围的操作
    • 掌握图表对象的创建和设置
  5. 可视化技巧

    • 条件格式化的应用
    • 散点图的创建和自定义

实用技巧

  1. 使用常量定义关键值
vba 复制代码
Const THRESHOLD_VALUE As Double = 1739
  1. 计时功能实现
vba 复制代码
startTime = Timer
executionTime = Format(Timer - startTime, "0.00")
  1. 动态范围处理
vba 复制代码
lastRow = .Cells(.Rows.Count, "G").End(xlUp).Row

V20250121

c 复制代码
Sub FindExceedingValues()
    Dim wsSource As Worksheet, wsCoord As Worksheet, wsResult As Worksheet
    Dim lastRow As Long
    Dim i As Long, itemCount As Long
    Dim dataArray() As Variant
    Dim results() As Variant
    Dim startTime As Double
    Const THRESHOLD_VALUE As Double = 1739 '设置阈值变量,方便修改
    Dim chtObj As ChartObject
    
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    startTime = Timer
    
    'Set up worksheets
    Set wsSource = ThisWorkbook.Worksheets("Nodal Reactions")
    Set wsCoord = ThisWorkbook.Worksheets("Obj Geom - Point Coordinates")
    
    'Create or clear result worksheet
    On Error Resume Next
    Set wsResult = ThisWorkbook.Worksheets("04.Over Points List")
    If wsResult Is Nothing Then
        Set wsResult = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
        wsResult.Name = "04.Over Points List"
    End If
    On Error GoTo 0
    
    wsResult.Cells.Clear
    
    'Get last row of source data
    With wsSource
        lastRow = .Cells(.Rows.Count, "G").End(xlUp).Row
        
        'Read all data at once
        dataArray = .Range(.Cells(1, 1), .Cells(lastRow, 10)).Value
        
        'Initialize results array
        itemCount = 0
        ReDim results(1 To 10, 1 To 1)
        
        'Process data array
        For i = 2 To UBound(dataArray, 1)
            If IsNumeric(dataArray(i, 7)) Then
                If Abs(dataArray(i, 7)) > THRESHOLD_VALUE Then
                    itemCount = itemCount + 1
                    ReDim Preserve results(1 To 10, 1 To itemCount)
                    
                    'Store all columns
                    For j = 1 To 10
                        results(j, itemCount) = dataArray(i, j)
                    Next j
                End If
            End If
        Next i
    End With
    
    'Write results
    With wsResult
        'Write headers
        .Range("A1:J1") = Array("Node", "Point", "OutputCase", "CaseType", "Fx", "Fy", "Fz", "Mx", "My", "Mz")
        .Range("K1") = "X Coordinate"
        .Range("L1") = "Y Coordinate"
        .Range("M1") = "Exceeding Ratio" '新增列标题
        
        'Write data if any found
        If itemCount > 0 Then
            'Write main data
            For i = 1 To itemCount
                For j = 1 To 10
                    .Cells(i + 1, j) = results(j, i)
                Next j
            Next i
            
            'Add VLOOKUP formulas
            .Range("K2").Formula = "=VLOOKUP($B2,'Obj Geom - Point Coordinates'!$A:$C,2,FALSE)"
            .Range("L2").Formula = "=VLOOKUP($B2,'Obj Geom - Point Coordinates'!$A:$C,3,FALSE)"
            
            '添加比值计算公式
            .Range("M2").Formula = "=ABS(G2)/" & THRESHOLD_VALUE & "-1"
            
            'Fill down formulas if more than one row
            If itemCount > 1 Then
                .Range("K2:M2").AutoFill Destination:=.Range("K2:M" & itemCount + 1)
            End If
            
            'Format the worksheet
            With .Range("A1:M1")
                .Font.Bold = True
                .Interior.Color = RGB(200, 200, 200)
            End With
            
            With .Range("A1:M" & itemCount + 1)
                .Borders.LineStyle = xlContinuous
                .Columns.AutoFit
            End With
            
            .Range("A:D").NumberFormat = "@"
            .Range("M:M").NumberFormat = "0.00%" '设置比值列为百分比格式
            
            '添加数据条条件格式
            Dim formatRange As Range
            Set formatRange = .Range("M2:M" & itemCount + 1)
            formatRange.FormatConditions.Delete
            formatRange.FormatConditions.AddDatabar
            With formatRange.FormatConditions(1)
                .BarFillType = xlDataBarFillSolid
                .BarColor.Color = RGB(255, 0, 0) 'Red color
                .ShowValue = True
            End With
            
            '删除现有图表(如果存在)
            On Error Resume Next
            wsResult.ChartObjects.Delete
            On Error GoTo 0
            
        '创建散点图
        Set chtObj = wsResult.ChartObjects.Add( _
            Left:=.Range("O1").Left, _
            Top:=.Range("O1").Top, _
            Width:=800, _
            Height:=600)
        
        With chtObj.Chart
            .ChartType = xlXYScatter
            
            '添加数据系列
            .SeriesCollection.NewSeries
            With .SeriesCollection(1)
                .XValues = wsResult.Range("K2:K" & itemCount + 1)
                .Values = wsResult.Range("L2:L" & itemCount + 1)
                .MarkerStyle = xlMarkerStyleCircle
                .MarkerSize = 8
                .Format.Fill.ForeColor.RGB = RGB(255, 0, 0)
                
                '为每个点添加数据标签
                .HasDataLabels = True
                With .DataLabels
                    .ShowValue = False
                    .ShowCategoryName = False
                    .ShowSeriesName = False
                    .Format.TextFrame2.TextRange.Font.Size = 8
                    
                    '设置每个点的数据标签为对应的M列值
                    On Error Resume Next  '添加错误处理
                    Dim pt As Integer
                    For pt = 1 To .Count
                        .Item(pt).Text = Format(wsResult.Cells(pt + 1, "M").Value, "0.00%")
                    Next pt
                    On Error GoTo 0
                End With
            End With
            
            '设置图表标题和轴标题
            .HasTitle = True
            .ChartTitle.Text = "Distribution of Exceeding Points"
            
            With .Axes(xlCategory, xlPrimary)
                .HasTitle = True
                .AxisTitle.Text = "X Coordinate"
            End With
            
            With .Axes(xlValue, xlPrimary)
                .HasTitle = True
                .AxisTitle.Text = "Y Coordinate"
            End With
            
            '添加图例
            .HasLegend = False
        End With
        End If
    End With
    
    'Restore settings
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
    
    'Show completion message
    Dim executionTime As String
    executionTime = Format(Timer - startTime, "0.00")
    
    If itemCount = 0 Then
        MsgBox "No values exceeding " & THRESHOLD_VALUE & " were found in Column Fz." & vbNewLine & _
               "Execution time: " & executionTime & " seconds", vbInformation
    Else
        MsgBox itemCount & " values exceeding " & THRESHOLD_VALUE & " were found and listed." & vbNewLine & _
               "Execution time: " & executionTime & " seconds", vbInformation
    End If
End Sub

V20250122 add lower point list (for reduncancy reference)

c 复制代码
Sub FindExceedingValues()
    Dim wsSource As Worksheet, wsCoord As Worksheet, wsResult As Worksheet, wsResultLow As Worksheet
    Dim lastRow As Long
    Dim i As Long, itemCount As Long, itemCountLow As Long
    Dim dataArray() As Variant
    Dim results() As Variant, resultsLow() As Variant
    Dim startTime As Double
    Const THRESHOLD_VALUE_HIGH As Double = 1850 '上限阈值
    Const THRESHOLD_VALUE_LOW As Double = 925  '下限阈值
    Dim chtObj As ChartObject
    
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    startTime = Timer
    
    'Set up worksheets
    Set wsSource = ThisWorkbook.Worksheets("Nodal Reactions")
    Set wsCoord = ThisWorkbook.Worksheets("Obj Geom - Point Coordinates")
    
    'Create or clear result worksheets
    On Error Resume Next
    Set wsResult = ThisWorkbook.Worksheets("04.Over Points List")
    Set wsResultLow = ThisWorkbook.Worksheets("05.Lower Points List")
    
    If wsResult Is Nothing Then
        Set wsResult = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
        wsResult.Name = "04.Over Points List"
    End If
    
    If wsResultLow Is Nothing Then
        Set wsResultLow = ThisWorkbook.Worksheets.Add(After:=wsResult)
        wsResultLow.Name = "05.Lower Points List"  ' 确保这里的名称与前面的Set语句一致
    End If
    On Error GoTo 0
    
    ' 确保清除正确的工作表
    wsResult.Cells.Clear
    wsResultLow.Cells.Clear
    
    'Get last row of source data
    With wsSource
        lastRow = .Cells(.Rows.Count, "G").End(xlUp).Row
        
        'Read all data at once
        dataArray = .Range(.Cells(1, 1), .Cells(lastRow, 10)).Value
        
        'Initialize results arrays
        itemCount = 0
        itemCountLow = 0
        ReDim results(1 To 10, 1 To 1)
        ReDim resultsLow(1 To 10, 1 To 1)
        
        'Process data array
        For i = 2 To UBound(dataArray, 1)
            If IsNumeric(dataArray(i, 7)) Then
                If Abs(dataArray(i, 7)) > THRESHOLD_VALUE_HIGH Then
                    itemCount = itemCount + 1
                    ReDim Preserve results(1 To 10, 1 To itemCount)
                    
                    'Store all columns for high values
                    For j = 1 To 10
                        results(j, itemCount) = dataArray(i, j)
                    Next j
                ElseIf Abs(dataArray(i, 7)) < THRESHOLD_VALUE_LOW Then
                    itemCountLow = itemCountLow + 1
                    ReDim Preserve resultsLow(1 To 10, 1 To itemCountLow)
                    
                    'Store all columns for low values
                    For j = 1 To 10
                        resultsLow(j, itemCountLow) = dataArray(i, j)
                    Next j
                End If
            End If
        Next i
    End With
    
    '处理超过上限的数据
    ProcessWorksheet wsResult, results, itemCount, THRESHOLD_VALUE_HIGH, "Over"
    
    '处理低于下限的数据
    ProcessWorksheet wsResultLow, resultsLow, itemCountLow, THRESHOLD_VALUE_LOW, "Under"
    
    'Restore settings
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
    
    'Show completion message
    Dim executionTime As String
    executionTime = Format(Timer - startTime, "0.00")
    
    MsgBox "Found " & itemCount & " values exceeding " & THRESHOLD_VALUE_HIGH & vbNewLine & _
           "Found " & itemCountLow & " values below " & THRESHOLD_VALUE_LOW & vbNewLine & _
           "Execution time: " & executionTime & " seconds", vbInformation
End Sub

Sub ProcessWorksheet(ws As Worksheet, results() As Variant, itemCount As Long, thresholdValue As Double, sheetType As String)
    Dim chtObj As ChartObject
    Dim j As Long
    
    With ws
        'Write headers
        .Range("A1:J1") = Array("Node", "Point", "OutputCase", "CaseType", "Fx", "Fy", "Fz", "Mx", "My", "Mz")
        .Range("K1") = "X Coordinate"
        .Range("L1") = "Y Coordinate"
        .Range("M1") = "Ratio" '新增列标题
        
        If itemCount > 0 Then
            'Write main data
            For i = 1 To itemCount
                For j = 1 To 10
                    .Cells(i + 1, j) = results(j, i)
                Next j
            Next i
            
            'Add VLOOKUP formulas
            .Range("K2").Formula = "=VLOOKUP($B2,'Obj Geom - Point Coordinates'!$A:$C,2,FALSE)"
            .Range("L2").Formula = "=VLOOKUP($B2,'Obj Geom - Point Coordinates'!$A:$C,3,FALSE)"
            
            '添加比值计算公式
            If sheetType = "Over" Then
                .Range("M2").Formula = "=ABS(G2)/" & thresholdValue & "-1"
            Else
                .Range("M2").Formula = "=1-ABS(G2)/" & thresholdValue
            End If
            
            'Fill down formulas if more than one row
            If itemCount > 1 Then
                .Range("K2:M2").AutoFill Destination:=.Range("K2:M" & itemCount + 1)
            End If
            
            'Format the worksheet
            With .Range("A1:M1")
                .Font.Bold = True
                .Interior.Color = RGB(200, 200, 200)
            End With
            
            With .Range("A1:M" & itemCount + 1)
                .Borders.LineStyle = xlContinuous
                .Columns.AutoFit
            End With
            
            .Range("A:D").NumberFormat = "@"
            .Range("M:M").NumberFormat = "0.00%"
            
            '添加数据条条件格式
            Dim formatRange As Range
            Set formatRange = .Range("M2:M" & itemCount + 1)
            formatRange.FormatConditions.Delete
            formatRange.FormatConditions.AddDatabar
            With formatRange.FormatConditions(1)
                .BarFillType = xlDataBarFillSolid
                If sheetType = "Over" Then
                    .BarColor.Color = RGB(255, 0, 0) 'Red for over values
                Else
                    .BarColor.Color = RGB(0, 0, 255) 'Blue for under values
                End If
                .ShowValue = True
            End With
            
            '删除现有图表(如果存在)
            On Error Resume Next
            ws.ChartObjects.Delete
            On Error GoTo 0
            
            '创建散点图
            Set chtObj = ws.ChartObjects.Add( _
                Left:=.Range("O1").Left, _
                Top:=.Range("O1").Top, _
                Width:=800, _
                Height:=600)
            
            With chtObj.Chart
                .ChartType = xlXYScatter
                
                '添加数据系列
                .SeriesCollection.NewSeries
                With .SeriesCollection(1)
                    .XValues = ws.Range("K2:K" & itemCount + 1)
                    .Values = ws.Range("L2:L" & itemCount + 1)
                    .MarkerStyle = xlMarkerStyleCircle
                    .MarkerSize = 8
                    If sheetType = "Over" Then
                        .Format.Fill.ForeColor.RGB = RGB(255, 0, 0)
                    Else
                        .Format.Fill.ForeColor.RGB = RGB(0, 0, 255)
                    End If
                    
                    '为每个点添加数据标签
                    .HasDataLabels = True
                    With .DataLabels
                        .ShowValue = False
                        .ShowCategoryName = False
                        .ShowSeriesName = False
                        .Format.TextFrame2.TextRange.Font.Size = 8
                        
                        On Error Resume Next
                        Dim pt As Integer
                        For pt = 1 To .Count
                            .Item(pt).Text = Format(ws.Cells(pt + 1, "M").Value, "0.00%")
                        Next pt
                        On Error GoTo 0
                    End With
                End With
                
                '设置图表标题和轴标题
                .HasTitle = True
                If sheetType = "Over" Then
                    .ChartTitle.Text = "Distribution of Exceeding Points"
                Else
                    .ChartTitle.Text = "Distribution of Lower Points"
                End If
                
                With .Axes(xlCategory, xlPrimary)
                    .HasTitle = True
                    .AxisTitle.Text = "X Coordinate"
                End With
                
                With .Axes(xlValue, xlPrimary)
                    .HasTitle = True
                    .AxisTitle.Text = "Y Coordinate"
                End With
                
                '添加图例
                .HasLegend = False
            End With
        End If
    End With
End Sub
相关推荐
测试199813 小时前
Pytest+Allure+Excel接口自动化测试框架实战
自动化测试·软件测试·python·测试工具·职场和发展·excel·pytest
东京老树根1 天前
Excel 技巧20 - 在Excel中输入内容时自动添加边框(★★)
笔记·学习·excel
qq_407110921 天前
Libreoffice实现Word、Excel在线预览
java·word·excel
高克莱1 天前
【Java实现 通过Easy Excel完成对excel文本数据的读写】
java·spring boot·excel
upcdxlq1 天前
java poi excel 富文本粗体无效
excel
CodeCraft Studio2 天前
【实用技能】如何借助Excel处理控件Aspose.Cells,使用 C# 锁定 Excel 中的单元格
开发语言·c#·excel
csdn_aspnet2 天前
在 ASP.NET Core 6.0 Web API 中将 Excel 文件数据上传并保存到数据库中
数据库·excel·webapi·.net6.0
quweiie2 天前
tp8读取mysql导出excel
android·mysql·excel
惊鸿一博2 天前
宏_wps_宏修改word中所有excel表格的格式_设置字体对齐格式_删除空行等
word·excel·wps