【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
相关推荐
葡萄城技术团队18 小时前
从100秒到10秒的性能优化,你真的掌握 Excel 的使用技巧了吗?
excel
QQ3596773452 天前
ArcGIS Pro实现基于 Excel 表格批量创建标准地理数据库(GDB)——高效数据库建库解决方案
数据库·arcgis·excel
星空的资源小屋3 天前
Digital Clock 4,一款免费的个性化桌面数字时钟
stm32·单片机·嵌入式硬件·电脑·excel
揭老师高效办公4 天前
在Excel和WPS表格中批量删除数据区域的批注
excel·wps表格
我是zxb4 天前
EasyExcel:快速读写Excel的工具类
数据库·oracle·excel
辣香牛肉面4 天前
[Windows] 搜索文本2.6.2(从word、wps、excel、pdf和txt文件中查找文本的工具)
word·excel·wps·搜索文本
ljf88384 天前
Java导出复杂excel,自定义excel导出
java·开发语言·excel
tebukaopu1484 天前
json文件转excel
json·excel
shizidushu4 天前
How to work with merged cells in Excel with `openpyxl` in Python?
python·microsoft·excel·openpyxl
Eiceblue5 天前
使用 C# 设置 Excel 单元格格式
开发语言·后端·c#·.net·excel