Создайте график столбца с пробелами между данными

#excel #vba #graph

Вопрос:

Я пытаюсь создать графики каждого столбца данных на листе. На данный момент он работает до тех пор, пока в столбце данных нет пробелов, но мне нужно, чтобы он был достаточно надежным, чтобы он работал, если в данных есть пробелы. Данные вводятся пакетами с различными столбцами разной длины из-за различных требований к измерениям. Каждая из строк также будет иметь идентификатор в первом столбце, указывающий, из какого пакета данных взята эта строка (см. Прикрепленный файл). Поскольку столбец идентификатора будет иметь ту же длину, что и самый длинный столбец данных, я сравниваю последнюю строку этого столбца с нижней строкой любого данного столбца данных, чтобы убедиться, что все данные отображаются на графике. Однако прямо сейчас он застревает в цикле, если в данных есть пробел.

 Sub GraphAllColumns()  Dim col As Range 'The cell at the top of the data column  Dim bottomRow As Range  Dim bottomData As Range    Set col = ActiveSheet.Range("B7")  Set bottomRow = Range("A7").End(xlDown)    col.Select    If Not IsEmpty(Selection) Then 'If the worksheet is empty, nothing happens  Do  Set bottomData = Selection.End(xlDown)  If bottomRow.Row lt;= bottomData.Row Then  'Iterate through every column, select all the data in that column  'then call the create graph subroutine  Call CreateGraph  ActiveCell.Offset(0, 1).Select  Else  If IsEmpty(Selection.End(xlDown)) Then  Call CreateGraph  ActiveCell.Offset(0, 1).Select  Else  Range(Selection, Selection.End(xlDown)).Select  End If  End If  Loop Until IsEmpty(Selection)  End If   End Sub  Here's the CreateGraph subroutine as well. I'm happy the way that it works. I know it isn't the best way, but this is my first time using VBA.   Sub CreateGraph()  Dim startCell As Range 'Starting cell (important for column selection)  Dim graphRange As Range    Set startCell = Selection  Set graphRange = Range(startCell, startCell.End(xlDown)) 'Selects all data in column    'Create chart, define chart type and source data  ActiveSheet.Shapes.AddChart.Select  ActiveChart.ChartType = xlLine  ActiveChart.SetSourceData Source:=graphRange    'Change chart location so that all charts on a sheet are stacked in top left corner  With ActiveChart.Parent  .Top = Range("A1")  .Left = Range("A1")  End With    'Change chart title and other attributes  With ActiveChart  .HasTitle = True  .ChartTitle.Text = startCell.Offset(-2, 0).Value    End With  End Sub  

введите описание изображения здесь

Комментарии:

1. Set bottomRow = Cells(Rows.Count, "A").End(xlUp) это лучший подход

2. IsEmpty(Selection) не делает того, что вы думаете, — он вернется False , даже если данных нет.

3. Здесь был бы полезен скриншот того, как представлены ваши данные. «Посмотреть прикрепленный файл» — файла нет?

4. Извините за это, я отредактировал картинку. Я совершенно забыл об этом.

5. Итак, каков будет диапазон для первого участка? Все еще не уверен, что я точно следую инструкциям.

Ответ №1:

Возможно, я все еще неправильно понимаю, чего вы хотите, но это должно помочь вам начать.

 Sub PlotDataById()    Dim dict As Object, id, ws As Worksheet, rngId As Range    Set ws = ActiveSheet 'or whatever    Set dict = IdRanges(ws.Range("B3")) 'get the ranges for each id    For Each id In dict  Set rngId = dict(id).Offset(0, 1) 'first set of data  Debug.Print "Plotting id - " amp; id amp; ":" amp; rngId.Address  Do While Application.CountA(rngId) gt; 0  'use resize() to pass only the occupied range  CreateGraph rngId.Resize(Application.CountA(rngId)), id  Set rngId = rngId.Offset(0, 1) 'next column over  Loop  Next id   End Sub  'Capture the ranges occupied by each id in a list, starting at `startCell` ' Assumes list is sorted by id Function IdRanges(startCell As Range) As Object  Dim c As Range, id, currId, cStart As Range, dict As Object  Set dict = CreateObject("scripting.dictionary")    currId = Chr(0) 'some non-value  Set c = startCell  Do While Len(c.Value) gt; 0  id = c.Value  If id lt;gt; currId Then  If Not cStart Is Nothing Then  dict.Add currId, c.Parent.Range(cStart, c.Offset(-1, 0))  End If  Set cStart = c  currId = id  End If  Set c = c.Offset(1, 0)  Loop  dict.Add currId, c.Parent.Range(cStart, c.Offset(-1, 0))  Set IdRanges = dict End Function  'Create a plot of `rngData` with title `chtTitle` Sub CreateGraph(rngData As Range, chtTitle)  Dim co As Shape, cht As Chart, ws As Worksheet  Set ws = rngData.Parent  Set co = ws.Shapes.AddChart  With co.Chart  .ChartType = xlLine  .SetSourceData Source:=rngData  .HasTitle = True  .ChartTitle.Text = chtTitle  End With  With co 'all charts on a sheet are stacked in top left corner  .Top = ws.Range("A1").Top  .Left = ws.Range("A1").Left  End With End Sub  

Использование Select/ActiveCell-не очень надежный способ структурирования кода, и, как правило, вы можете избежать почти всех применений этого подхода.