在比Excel窗口更宽的Excel图表中检测第一个和最后一个可见点

我有一个包含烛台图表的Excel工作表,但是对于这个问题,它可能是一个普通的二维折线图,或者是任何一个具有横轴的图表。

图表的数据源不是math函数, 而是代表价格的任意数据,从另一个工作表的列中读取。

我的图表比工作表窗口宽许多倍 – 而不是Excel窗口本身。 我通过简单地使用工作表的普通水平滚动条来水平浏览图表,滚动工作表(包括图表中的工作表)。

我将button放在同一工作表中,通过VBA代码手动调整图表的垂直比例(Y轴),因为当水平滚动时,可见的新图表值可能需要显示不同的最小和最大Y轴值在一个最佳的方式。

我想用自动缩放replace手动缩放:在每次滚动之后,我需要知道最左侧的可见图表点和最右侧 – 这是第一个和最后一个可见点。 从那里我将计算出最好的Y-规模,并将其设置在图表中。

所以我试图写VBA代码来检测第一个和最后一个可见点。 Chart对象似乎没有相关的方法或属性,到目前为止,我无法find方法来做到这一点。 所以这是我的问题。

Chart.AutoScaling属性不会影响整个图表,而我的目标是设置一个仅适用于图表当前可见部分的垂直比例。 所以我需要find图表的第一个和最后一个可见点。

这个图表的用户可能有一个和Excel 2007一样古老的Excel版本,所以一个可以使用旧的版本的解决scheme是最优的,但是需要更新的Excel版本的解决scheme也会很好。

我很less发表另一个答案,所以这已经有了一些想法。

考虑一个只显示数据的select部分的dynamic图表,而不是显示所有数据的静态图表。 考虑一下,不是build立一个横跨多个屏幕宽度的图表,你可以有一个完美适合屏幕的图表,但是用户可以确定他们想要在该图表中看到什么。

然后给用户一些控制单元,他们可以在那里input图表数据的起始点,另一个控件可以确定他们想要在图表中看到多less个蜡烛/条/点。

通过用户提供的信息,您可以应用已build立的dynamic制图技术,如图表范围的命名公式。 然后在顶部撒上一点VBA,以确定所选图表范围的最小值和最大值。

让我知道如果你想看到这种技术的样本,我会添加一个链接。 实际上并不是那么困难,而且比滚动窗口左右消失的图表更好的用户体验。

编辑 :我创build了一个示例文件,您可以使用此Dropbox链接下载

您需要为此文件启用macros。

顶部图表显示所有数据。

第26行中的图表使用dynamic范围。 用户可以操作F17和F18来select一个起点和要绘制的行数。 然后,行26中的图表使用Excel的默认值,以便像Excel那样使用一些填充来适当地修改数值轴。

第42行的图表(爱这个数字)将覆盖Exel的默认值,并分别使用F23和F24中的值作为最小值和最大值。 这是通过一个工作表变更事件macros来完成的,只要工作表中的单元格发生更改,就会运行该macros。

有很多方法可以微调和改进这种方法,例如,只有在F23或F24中的图表参数发生变化时才会触发macros,但这不是重点。

重点是您可以使用dynamic范围名称在图表中显示您的数据select。 没有任何代码,但让Excel决定Y轴的最小值和最大值应该是什么。 像D26中的图表一样。

如果要更多地控制Y轴的最小值和最大值,请使用D42中的代码版本和图表。

乐于提问。

在VBA中,我不够精确,为此提供了精确的代码,但从概念上讲,如果水平滚动工作表,应该有一种方法来确定可见窗口中左上angular单元格的地址,例如使用ActiveWindow.VisibleRange.Cells(1,1)并沿着相同的逻辑行,如果知道列宽和缩放因子,则可以确定可见窗口的最后一个单元格。

然后,您可以将这些可见单元格及其各自的地址与图表数据源中的相关范围连接起来。 例如,如果可见范围是列A到M,则图表中的数据范围必须是第1行到第55行,如果可见范围是列M到Z,则图表中的数据范围必须是第55行到第100行。您可能需要为这种关系制定一个转换公式。

然后,您可以抓取将在图表中绘制的源数据中的相关值,并处理数值轴的最小值和最大值。

这是根据可见的x值缩放轴的function。

我试图评论它,但逻辑如下:

  • 使用.VisibleRange属性获取可见范围
  • 获取可见范围和绘图区域的左右点
  • 计算最左边和最右边的可见 x值,然后find最接近的实际数据点。 这避免了必须假设等距x数据
  • 获取数据中这些极值的索引,以便获得相应的y值。
  • 将坐标轴缩放到这些y值

注意:这当前依赖于ActiveChart对象,使用具有给定名称的定义图表对象会更加健壮。 这取决于您的具体使用情况。

码:

 Sub scaley() ' Get visible range Dim visrange As Range Set visrange = ActiveWindow.VisibleRange ' Get left and right in points Dim L As Double, R As Double L = visrange.Left R = visrange.Cells(visrange.Cells.Count).Offset(0, 1).Left ' Get left and right of chart, relies on chart being active ' could easily replace with calling your chart by name Dim chtL As Double, chtR As Double Dim cht As Chart Set cht = ActiveChart chtL = cht.Parent.Left + cht.PlotArea.Left chtR = chtL + cht.PlotArea.Width ' Get visible region by percentage Dim pL As Double, pR As Double pL = WorksheetFunction.Max((L - chtL) / (chtR - chtL), 0) pR = WorksheetFunction.Min((R - chtL) / (chtR - chtL), 1) ' Get x axis values, and the visible x axis range Dim xval() As Variant xval = cht.SeriesCollection(1).XValues Dim xmin As Double, xmax As Double, xrange As Double xmin = WorksheetFunction.Min(xval) xrange = WorksheetFunction.Max(xval) - xmin xmax = xmin + pR * xrange xmin = xmin + pL * xrange ' Get actual corresponding x values Dim imin As Long, imax As Long For imin = LBound(xval) To UBound(xval) If xval(imin) >= xmin Then Exit For Next imin For imax = UBound(xval) To LBound(xval) Step -1 If xval(imax) <= xmax Then Exit For Next imax ' Get y values in the visible range Dim allyval() As Variant, yval() As Variant allyval = cht.SeriesCollection(1).Values ReDim yval(0 To imax - imin) Dim i As Long For i = imin To imax yval(i - imin) = allyval(i) Next i ' scale axes, including buffer so max/min values dont sit right on edge Dim buffer As Double buffer = 0.1 cht.Axes(xlValue).MaximumScale = WorksheetFunction.Max(yval) + buffer cht.Axes(xlValue).MinimumScale = WorksheetFunction.Min(yval) - buffer End Sub 

以下是一些示例输出。 我用任意数据 x = -10, -9, ..., 10y = 100, 81, 64, 49, ..., 81, 100 (这是x^2 )来创build散点图,然后跑在不同的窗口位置的子。

图表大小没有改变,我只是改变我的窗口大小/滚动,确保图表被选中(见上面的“注意”),并运行子:

放大1

放大2


如果你真的需要触发滚动事件的这个子,那么你可能想看看这里: cpearson – DetectScroll 。 虽然这不是一件简单的事情! 一个更容易的select是在顶部(或类似的东西)上有一个非常宽的button,可以调用上面的scaley子。