当前位置:首页>Excel>我用 VBA 管 Excel 图表:从创建到导出、事件、迷你图,一篇讲清楚

我用 VBA 管 Excel 图表:从创建到导出、事件、迷你图,一篇讲清楚

  • 2026-05-11 09:29:45
我用 VBA 管 Excel 图表:从创建到导出、事件、迷你图,一篇讲清楚

做 Excel 报表时,我最怕两件事:图表多,改起来全靠点鼠标;数据一换,图表范围、标题、标签又要手动改。VBA 图表的价值就在这里。它不是只会“画一张图”,它能把图表当成对象来管:创建、移动、改样式、换数据、批量导出、响应点击,还能做迷你图报表。

我这篇用自拟案例来讲。主线是一个连锁咖啡店看板,旁边穿插客服效果、SKU 出库、基金趋势这些小场景。案例和配图都重新做了,不沿用资料里的例子。

我先把图表对象认清楚

很多人写 VBA 图表卡住,不是语法问题,是对象没找对。

我会这样记:

  • 嵌入式图表在普通工作表里,它有一个外壳,叫 ChartObject,也能从 Shapes 里访问。外壳管位置、大小、名称。
  • 真正的图表本体叫 Chart。标题、系列、坐标轴、图例、绘图区,都在 Chart 下面。
  • 图表工作表不是嵌在某个单元格区域里,而是工作簿里单独的一张图表页,入口是 Workbook.Charts

我平时写代码会尽量写完整引用:

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
Sub RenameDashboardChart()Dim ws As WorksheetDim co As ChartObjectSet ws = ThisWorkbook.Worksheets("看板")Set co = ws.ChartObjects("chtStoreMonth")    co.Chart.HasTitle = True    co.Chart.ChartTitle.Text = "4 月门店销售"EndSub

这里的 co 是外壳,co.Chart 才是图表。说白了,外壳像相框,图表像相框里的画。

还有一个小坑我会刻意避开:ChartObject.Name 和 Chart.Name 可能不是同一个值。定位嵌入式图表时,我更喜欢用 ChartObject 的名字,比如 ws.ChartObjects("chtStoreMonth")

我会用宏录制器,但不会照抄录制结果

宏录制器很有用。遇到不熟的属性,我会录一小段,看看 Excel 自己怎么写。可录制器常常生成这类代码:

  • 1
  • 2
ActiveSheet.ChartObjects("Chart 1").ActivateActiveChart.ChartTitle.Text = "4 月门店销售"

这段能跑,但批量处理时很容易出问题。我的习惯是录完就改成对象引用:

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
Dim ws As WorksheetDim co As ChartObjectSet ws = ThisWorkbook.Worksheets("看板")Set co = ws.ChartObjects("chtStoreMonth")co.Chart.ChartTitle.Text = "4 月门店销售"

SelectActivateActiveChart 不是不能用,只是它们依赖当前界面状态。代码越靠当前界面,越容易被用户点一下鼠标打断。

我创建图表时,会先分清两种放法

我一般这么选:看板里需要很多图,就用嵌入式图表;需要单独打印、单独展示的大图,就用图表工作表。

真正的图表可能有的人不知道,可以手动创建:

选中一个工作表标签页,右键,插入;

界面长这样:

嵌入式图表:放在工作表里

Excel 2013 之后,我常用 Shapes.AddChart2。它能直接指定样式、类型、位置和大小。

下面这个例子会在“看板”工作表里创建一张门店销售柱形图:

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
SubBuildCoffeeSalesChart()DimwsAsWorksheetDimshpAsShapeDimrngAsRangeSetws=ThisWorkbook.Worksheets("看板")Setrng=ws.Range("A1:F6")Setshp=ws.Shapes.AddChart2(_Style:=227,_XlChartType:=xlColumnClustered,_Left:=ws.Range("H2").Left,_Top:=ws.Range("H2").Top,_Width:=520,_Height:=300)shp.Name="chtStoreMonth"Withshp.Chart.SetSourceDataSource:=rng.HasTitle=True.ChartTitle.Text="4 月门店销售".SetElementmsoElementLegendBottomEndWithEndSub

如果要兼容旧版 Excel,我会改用 ChartObjects.Add

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
Sub BuildChartForOldExcel()Dim ws As WorksheetDim co As ChartObjectSet ws = ThisWorkbook.Worksheets("看板")Set co = ws.ChartObjects.Add(Left:=360, Top:=40, Width:=520, Height:=300)    co.Name = "chtStoreMonth"With co.Chart        .ChartType = xlColumnClustered        .SetSourceData Source:=ws.Range("A1:F6")        .HasTitle = True        .ChartTitle.Text = "4 月门店销售"EndWithEndSub

图表工作表:整张 Sheet 就是一张图

图表工作表的入口是 ThisWorkbook.Charts

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
Sub BuildSalesChartSheet()Dim ws As WorksheetDim cht As ChartSet ws = ThisWorkbook.Worksheets("月度数据")Set cht = ThisWorkbook.Charts.AddWith cht        .Name = "月销售大图"        .ChartType = xlLineMarkers        .SetSourceData Source:=ws.Range("A1:M4")        .HasTitle = True        .ChartTitle.Text = "门店月销售趋势"EndWithEndSub

我会把 Charts("月销售大图") 当成一张特殊的工作表来理解。它没有 ChartObject 外壳,自己就是 Chart

我写图表代码时,会走固定 6 步

我的写法基本都是这 6 步:准备数据区域,放下图表外壳,绑定数据,确定图表类型,处理标题和样式,导出或加交互。

这套写法有个好处:从创建一张图,扩展到创建几十张图,只需要把“数据区域”和“图表位置”放进循环里。

我改图表样式,不会一张张点鼠标

图表样式常见的动作有这些:

  • 改 ChartType,比如柱形图、折线图、散点图。
  • 改标题、图例、坐标轴、网格线。
  • 改 ChartStyle 和 ChartColor。不同版本编号会有差异,Excel 2013 之后常见样式编号更多。
  • 改某条系列、某个点,比如线宽、填充、标记。
  • 用 SetElement 添加或删除图表元素。

我一般写一个小过程,传入任何 Chart 都能统一处理:

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
SubPolishChart(ByValchtAsChart,ByValtitleTextAsString)Withcht.HasTitle=True.ChartTitle.Text=titleText.SetElementmsoElementLegendBottom.SetElementmsoElementPrimaryValueGridLinesMajor.ChartStyle=201.ChartColor=13If.SeriesCollection.Count>0ThenWith.FullSeriesCollection(1).Format.Line.Weight=2.25.MarkerSize=6EndWithEndIfEndWithEndSub

FullSeriesCollection 我也会用到。它能处理完整系列集合,适合有筛选状态的图表。只是旧版 Excel 里不一定支持,我会按版本情况换回 SeriesCollection

我会少用 ActiveChart,但也要懂它

ActiveChart 指当前激活的图表。如果当前没激活图表,它就是 Nothing

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
Sub CheckActiveChart()If ActiveChart IsNothingThen        MsgBox "当前没有激活图表"Else        MsgBox "当前图表标题是:" & ActiveChart.ChartTitle.TextEndIfEndSub

激活嵌入式图表可以这样写:

  • 1
Worksheets("看板").ChartObjects("chtStoreMonth").Activate

激活图表工作表可以这样写:

  • 1
ThisWorkbook.Charts("月销售大图").Activate

取消激活没有专门的 Deactivate 方法。我会选中一个单元格:

  • 1
Worksheets("看板").Range("A1").Select

还有一个细节:如果用户选中了图表里的标题、坐标轴、数据点,ActiveChart 依然可能返回父图表。所以我做“当前是否在图表里”的判断时,会把这个情况也算进去。

我移动、删除图表时,会重新接住对象引用

把嵌入式图表移到图表工作表,可以用 Location

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
Sub MoveEmbeddedChartToChartSheet()Dim ws As WorksheetDim cht As ChartSet ws = ThisWorkbook.Worksheets("看板")Set cht = ws.ChartObjects("chtStoreMonth").Chart    cht.Location Where:=xlLocationAsNewSheet, Name:="门店销售大图"EndSub

把图表工作表移回普通工作表也可以:

  • 1
  • 2
  • 3
  • 4
Sub MoveChartSheetBack()    ThisWorkbook.Charts("门店销售大图").Location _Where:=xlLocationAsObject, Name:="看板"End Sub

我会在 Location 之后重新获取图表引用,因为图表所在位置变了,旧引用有时不再适合继续用。

删除嵌入式图表:

  • 1
Worksheets("看板").ChartObjects("chtStoreMonth").Delete

删除图表工作表时,Excel 可能弹确认框,我会临时关掉提示,再马上打开:

  • 1
  • 2
  • 3
  • 4
  • 5
SubDeleteChartSheetQuietly()Application.DisplayAlerts = FalseThisWorkbook.Charts("门店销售大图").DeleteApplication.DisplayAlerts = TrueEndSub

这类代码我会用错误处理包起来,避免中途报错后 DisplayAlerts 一直关着。

我批量处理图表,会同时扫嵌入式图表和图表工作表

很多工作簿里两种图表都有。只循环 ChartObjects,图表工作表会漏掉;只循环 Charts,嵌入式图表会漏掉。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
Sub PolishAllChartsInWorkbook()Dim wb As WorkbookDim ws As WorksheetDim co As ChartObjectDim cht As ChartSet wb = ThisWorkbookForEach ws In wb.WorksheetsForEach co In ws.ChartObjects   PolishChartco.Chart,ws.Name& " 图表"Next coNext wsForEach cht In wb.Charts        PolishChart cht, cht.NameNext chtEndSub

调整大小和对齐时,我只改外壳属性:LeftTopWidthHeight

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
Sub ArrangeChartsOnDashboard()Dim ws As WorksheetDim co As ChartObjectDim i AsLong, cols AsLongDimleft0AsDouble,top0AsDouble,wAsDouble,hAsDouble,gapAsDoubleSet ws = ThisWorkbook.Worksheets("看板")    cols = 3    left0 = 30    top0 = 80    w = 320    h = 210    gap = 18ForEach co In ws.ChartObjects        i = i + 1        co.Width = w        co.Height = h   co.Left=left0+((i-1)Modcols)*(w+ gap)   co.Top=top0+Int((i-1)/cols)*(h+ gap)Next coEndSub

我用“小过程”批量创建很多小图

比如仓库运营里,我想看 12 个 SKU 最近 7 天出库趋势。手工做 12 张图太费劲,我会把“创建一张图”写成过程,再循环调用。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
Sub BuildSkuTrendCharts()Dim ws As WorksheetDim r AsLong, lastRow AsLongDim leftPos AsDouble, topPos AsDoubleSet ws = ThisWorkbook.Worksheets("SKU趋势")    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).RowFor r = 2To lastRow   leftPos=40+((r-2)Mod4)* 260   topPos=80+Int((r-2)/4)* 180        CreateSkuChart ws, r, leftPos, topPosNext rEndSubSub CreateSkuChart(ByVal ws As Worksheet, ByVal rowNum AsLong, _ByValleftPosAsDouble,ByValtopPosAsDouble)Dim co As ChartObjectDim rng As RangeSet rng = ws.Range(ws.Cells(rowNum, "B"), ws.Cells(rowNum, "H"))Set co = ws.ChartObjects.Add(leftPos, topPos, 230150)With co.Chart        .ChartType = xlLineMarkers        .SeriesCollection.NewSeries        .SeriesCollection(1).Name = ws.Cells(rowNum, "A").Value        .SeriesCollection(1).Values = rng        .SeriesCollection(1).XValues = ws.Range("B1:H1")        .HasTitle = True        .ChartTitle.Text = ws.Cells(rowNum, "A").Value        .Legend.DeleteEndWithEndSub

这段的关键不是 12 张图,而是“一个过程只管一张图”。以后要从 12 张变成 120 张,我只改循环范围。

我导出图表时,会优先用 Export

单张图表导出,Chart.Export 最直接。常见格式有 PNG、JPG、GIF。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
Sub ExportOneChart()Dim ws As WorksheetDim cht As ChartDim fileName AsStringSet ws = ThisWorkbook.Worksheets("看板")Set cht = ws.ChartObjects("chtStoreMonth").Chart    fileName = ThisWorkbook.Path & "\门店销售.png"    cht.Export Filename:=fileName, FilterName:="PNG"EndSub

我做公众号配图或发邮件附件时,经常用这个办法。要批量导出,就把它放进循环。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
Sub ExportAllEmbeddedCharts()Dim ws As WorksheetDim co As ChartObjectDim folder AsString    folder = ThisWorkbook.Path & "\chart_export\"If Dir(folder, vbDirectory) = ""Then MkDir folderForEach ws In ThisWorkbook.WorksheetsForEach co In ws.ChartObjects   co.Chart.Exportfolder&ws.Name&"_"&co.Name&".png""PNG"Next coNext wsEndSub

资料里也提到过一种老办法:把工作簿另存为 HTML,然后到生成的文件夹里找图表图片。我现在更常用 Export,因为路径和文件名都好控制。

我改图表数据,分三种情况处理

图表数据不是只能靠 SetSourceData。我会按场景选方法。

整张图换范围:SetSourceData

  • 1
cht.SetSourceData Source:=ws.Range("A1:F6")

这适合普通柱形图、折线图,数据结构比较规整。

单条系列换数据:SeriesCollection

  • 1
  • 2
  • 3
  • 4
  • 5
With cht.SeriesCollection(1)    .Name = ws.Range("B1")    .XValues = ws.Range("A2:A13")    .Values = ws.Range("B2:B13")EndWith

如果要新加一条系列:

  • 1
  • 2
  • 3
  • 4
  • 5
With cht.SeriesCollection.NewSeries    .Name = ws.Range("C1")    .XValues = ws.Range("A2:A13")    .Values = ws.Range("C2:C13")EndWith

直接看 SERIES 公式

每条系列背后都有一个 SERIES 公式,常见形式像这样:

  • 1
=SERIES(系列名, 分类标签, 数值, 顺序)

气泡图多一个参数:

  • 1
=SERIES(系列名, X值, Y值, 顺序, 气泡大小)

我想确认一张图到底用了哪些单元格时,会打印公式:

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
SubPrintSeriesFormula()DimsAsSeriesForEachsInActiveChart.SeriesCollectionDebug.Prints.FormulaNextsEndSub

要从公式里解析单元格区域,事情会比想象中麻烦。工作表名可能带空格,公式里可能有数组常量,地区设置还可能影响分隔符。所以我会先用 .Name.XValues.Values 这些属性处理常规需求,只有做图表审计工具时才去解析 SERIES 公式。

我会用选中单元格来驱动图表换数据

我很喜欢这种小交互:左边是指标清单,点“堂食订单”“外卖订单”“会员订单”,右边图表马上切换。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
PrivateSub Worksheet_SelectionChange(ByVal Target As Range)Dim cht As ChartIf Intersect(Target, Me.Range("A2:A8")) IsNothingThenExitSubIf Target.CountLarge > 1ThenExitSubSet cht = Me.ChartObjects("chtTrend").ChartWith cht.SeriesCollection(1)        .Name = Target.Value        .Values = Me.Range(Target.Offset(01), Target.Offset(06))        .XValues = Me.Range("B1:G1")EndWith    cht.ChartTitle.Text = Target.Value & " - 近 6 月趋势"EndSub

这里我没有重建图表,只换系列数据。体验会很顺,代码也短。

我给散点图加自定义标签,直接从单元格读文本

Excel 2013 之后,界面里可以选择“单元格中的值”做数据标签。VBA 里我常用更直接的办法:逐个点写 DataLabel.Text

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
Sub ApplyPointLabelsFromCells()Dim cht As ChartDim labelRng As RangeDim i AsLongSet cht = Worksheets("改版效果").ChartObjects("chtBeforeAfter").ChartSet labelRng = Worksheets("改版效果").Range("A2:A9")With cht.SeriesCollection(1)        .ApplyDataLabelsFor i = 1To .Points.Count            .Points(i).DataLabel.Text = labelRng.Cells(i, 1).TextNext iEndWithEndSub

这个场景我会用在散点图上,比如“改版前后转化金额”。只有点,没有标签,读者很难知道哪个点对应哪个页面。标签来自单元格,维护起来最省心。

我在用户窗体里显示图表,会先导出成图片

UserForm 里不能直接塞一个工作表图表。我常用的办法是:把图表导出成 GIF 或 PNG,再加载到 Image 控件。

  • 1
  • 2
  • 3
Sub ShowChartPreview()    frmChartPreview.ShowEnd Sub

在 UserForm 里写:

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
PrivateSub UserForm_Initialize()Dim tmpFile AsStringDim cht As Chart    tmpFile = Environ$("TEMP") & "\chart_preview.gif"Set cht = ThisWorkbook.Worksheets("看板") _        .ChartObjects("chtStoreMonth").Chart    cht.Export Filename:=tmpFile, FilterName:="GIF"Me.Image1.Picture = LoadPicture(tmpFile)EndSub

我会把这招用在小工具里,比如弹出一个“图表预览”窗口,让用户确认后再导出。

我理解图表事件后,报表就能“点图说话”

图表事件挺有意思。常见事件有这些:

事件
我会用在什么场景
Activate
 / Deactivate
图表被激活或离开时,显示或隐藏提示
Select
用户点中标题、系列、坐标轴等元素时,识别选中对象
MouseDown
 / MouseMove / MouseUp
点击柱子、鼠标悬停提示、拖动交互
BeforeDoubleClick
 / BeforeRightClick
双击或右键前接管动作
Resize
图表大小变化后重排元素
Calculate
图表重新计算后刷新附加信息
SeriesChange
用户改了数据点后同步记录

图表工作表的事件最简单,直接在图表页代码窗口写:

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
PrivateSub Chart_MouseDown(ByVal Button AsLong, _ByValShiftAsLong, _ByValxAsLong, _ByValyAsLong)Dim elementID AsLong, arg1 AsLong, arg2 AsLongMe.GetChartElement x, y, elementID, arg1, arg2If elementID = xlSeries Then        MsgBox "你点了第 " & arg2 & " 个数据点"EndIfEndSub

嵌入式图表麻烦一点,要用类模块。

类模块 CChartEvent

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
PublicWithEvents C As ChartPrivateSub C_MouseDown(ByVal Button AsLong, _ByValShiftAsLong, _ByValxAsLong, _ByValyAsLong)Dim elementID AsLong, arg1 AsLong, arg2 AsLong    C.GetChartElement x, y, elementID, arg1, arg2If elementID = xlSeries Then        Sheets("华东").ActivateEndIfEndSub

普通模块里要把事件对象存成模块级变量,不然过程结束后事件会失效:

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
Dim gChartEvent As CChartEventSub HookChartEvent()Set gChartEvent = New CChartEventSet gChartEvent.C = Worksheets("看板").ChartObjects("chtRegion").ChartEndSub

我会把这招用在区域看板里:点“华东”柱子,就跳到华东明细;点“华南”柱子,就跳到华南明细。用户不需要再找按钮。

我还会记住 4 个图表小技巧

每张嵌入式图表单独打印

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
Sub PrintEachChart()Dim co As ChartObjectForEach co In Worksheets("看板").ChartObjects        co.Chart.PrintOutNext coEndSub

这个适合一张工作表里有很多图,但老板想每张图单独一页。

做断开数据的图表

有时我需要发一份报告,不希望收件人改源数据后图表跟着变。我有两种做法。

一种是复制成图片:

  • 1
  • 2
ActiveChart.CopyPicture Appearance:=xlScreen, Format:=xlPictureWorksheets("报告").Paste

另一种是把系列的值写成数组,让图表不再指向单元格。这个写法要按图表类型小心处理,我通常只在固定模板里用。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
SubFreezeSeriesValues()DimsAsSeriesForEachsInActiveChart.SeriesCollections.Values=s.Valuess.XValues=s.XValuesNextsEndSub

MouseOver 显示说明文字

鼠标悬停到某个柱子上,我会用 GetChartElement 找出系列和点,再显示一个文本框。文本内容放在工作表单元格里,比如“2 月外卖订单上涨,因为新开了夜间配送”。

这类提示比默认 ChartTip 灵活。我通常会在 Activate 事件里关掉默认提示:

  • 1
  • 2
Application.ShowChartTipNames = FalseApplication.ShowChartTipValues = False

离开图表时再打开。

滚动图表

长序列数据不一定要一次全画出来。我的做法是用命名区域控制可见窗口,比如 StartDayNumDaysIncrement,再用按钮或宏改变 StartDay

  • 1
  • 2
  • 3
  • 4
  • 5
Sub MoveChartWindow()With Worksheets("日数据")        .Range("StartDay").Value = .Range("StartDay").Value + .Range("Increment").ValueEndWithEnd Sub

系列公式引用动态命名区域后,图表会跟着滚动。这个办法适合订单量、库存量、价格曲线这类长时间序列。

我把迷你图当成“单元格里的小图表”

迷你图是 Excel 2010 之后的功能,适合把一行数据的趋势放到末尾一列。

创建一组折线迷你图:

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
Sub AddFundSparklines()    Dim ws As WorksheetSet ws = ThisWorkbook.Worksheets("基金趋势")    ws.Range("H2:H9").SparklineGroups.Add _Type:=xlSparkLine, _        SourceData:="B2:G9"End Sub

常见类型有三种:

  • xlSparkLine:折线迷你图。
  • xlSparkColumn:柱形迷你图。
  • xlSparkColumnStacked100:赢输迷你图。

遍历迷你图组时,我会用下标:

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
Sub ReportSparklineGroups()Dim ws As WorksheetDim i AsLongSet ws = ThisWorkbook.Worksheets("基金趋势")For i = 1To ws.SparklineGroups.CountWith ws.SparklineGroups(i)            Debug.Print .Location.Address, .SourceData, .CountEndWithNext iEndSub

我不会把迷你图当普通 Chart 来管。它有自己的对象:SparklineGroups 和 Sparkline

我觉得最容易踩的坑,就这几类

我会怎么避开
ActiveChart
 是 Nothing
动手前先判断,能用对象引用就不用激活
嵌入式图表和图表工作表入口混了
嵌入式走 Worksheet.ChartObjects,图表页走 Workbook.Charts
只改 ChartObject,没改到 Chart
位置大小改外壳,标题系列改图本体
ChartObject.Name
 和 Chart.Name 对不上
定位嵌入式图表时用外壳名称
Location
 后旧引用不好用
移动后重新获取对象
录制器代码太依赖选择状态
把 SelectActivate 改成变量引用
解析 SERIES 公式太粗糙
常规需求先用 .Name.XValues.Values
事件对象失效
类模块对象存成模块级变量
删除图表工作表弹窗
临时关 DisplayAlerts,记得恢复

VBA 图表这事,说到底就是把图表当对象来管。创建时先定位置和数据,维护时拿住 Chart,批量时循环 ChartObjects 和 Charts,交互时用事件,输出时用 Export。我掌握这些之后,做 Excel 看板就不用一张张图慢慢点了。

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-05-18 15:52:11 HTTP/2.0 GET : https://h.sjds.net/a/509004.html
  2. 运行时间 : 0.338894s [ 吞吐率:2.95req/s ] 内存消耗:4,458.55kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=e6f31c295f45da62d219a0ea7fd96820
  1. /yingpanguazai/ssd/ssd1/www/h.sjds.net/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/h.sjds.net/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/h.sjds.net/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/h.sjds.net/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/h.sjds.net/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/h.sjds.net/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/h.sjds.net/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/h.sjds.net/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/h.sjds.net/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/h.sjds.net/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/h.sjds.net/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/h.sjds.net/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/h.sjds.net/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/h.sjds.net/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/h.sjds.net/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/h.sjds.net/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/h.sjds.net/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/h.sjds.net/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/h.sjds.net/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/h.sjds.net/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/h.sjds.net/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/h.sjds.net/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/h.sjds.net/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/h.sjds.net/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/h.sjds.net/runtime/temp/ad153693ed39fba6d1bda2fe72512cde.php ( 12.06 KB )
  140. /yingpanguazai/ssd/ssd1/www/h.sjds.net/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.010445s ] mysql:host=127.0.0.1;port=3306;dbname=h_sjds;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000932s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.046089s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.002913s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000931s ]
  6. SELECT * FROM `set` [ RunTime:0.000360s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.001389s ]
  8. SELECT * FROM `article` WHERE `id` = 509004 LIMIT 1 [ RunTime:0.013410s ]
  9. UPDATE `article` SET `lasttime` = 1779090732 WHERE `id` = 509004 [ RunTime:0.040414s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 65 LIMIT 1 [ RunTime:0.045838s ]
  11. SELECT * FROM `article` WHERE `id` < 509004 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.017129s ]
  12. SELECT * FROM `article` WHERE `id` > 509004 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000893s ]
  13. SELECT * FROM `article` WHERE `id` < 509004 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.011562s ]
  14. SELECT * FROM `article` WHERE `id` < 509004 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.004225s ]
  15. SELECT * FROM `article` WHERE `id` < 509004 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.031129s ]
0.341685s