Thanks #Rory! I was able to fix it and now I got a new bug
Run time error 1004/parameter not valid
at at .SeriesCollection(j).XValues = ws.Range(rs)
Could someone please help me?
'''
I am trying to make multiple charts. And each chart would have 20 different groups with legend.
The way I have tried is first make multiple charts by columns and then add for/n loop in my code (here tried to have every 20 rows for one each group
Sub horizontal()
Dim sh As Shape
Dim ws As Worksheet
Dim ch As Chart
Dim rd As Range
Dim i As Integer, j As Integer, k As Integer
Set ws = Sheets("S1")
On Error Resume Next
ws.ChartObjects.Delete
On Error GoTo 0
For i = 20 To 45
Set rs = ws.Range("s2:s21")
Set rd = ws.Range("f1:j10")
Set sh = ws.Shapes.AddChart2(240, xlXYScatterLines)
Set ch = sh.Chart
For j = 1 To 20
k = j * 20
With ch 'shape.chart'
.SetSourceData Union(rs, ws.Range(ws.Cells(2, i), ws.Cells(21, i)))
.SeriesCollection.NewSeries
.SeriesCollection(j).XValues = ws.Range("s2:s21")
.SeriesCollection(j).Values = ws.Range(ws.Cells(k - 18, i), ws.Cells(k + 1, i))
.HasTitle = True
.ChartTitle.Text = ws.Range("T1")
.HasLegend = True
End With
Next j
With sh
.Name = "cht" & (i - 19)
.Top = (i - 20) * rd.Height
.Left = rd.Left
.Width = rd.Width
.Height = rd.Height
End With
Next i
End Sub
I tried the below two codes but they didn'twork.
Sub horizontal()
Dim sh As Shape
Dim ws As Worksheet
Dim ch As Chart
Dim rd As Range
Dim i As Integer, j As Integer, k As Integer
Set ws = Sheets("S1")
On Error Resume Next
ws.ChartObjects.Delete
On Error GoTo 0
For i = 20 To 45
Set rs = ws.Range("s2:s21")
Set rd = ws.Range("f1:j10")
Set sh = ws.Shapes.AddChart2(240, xlXYScatterLines)
Set ch = sh.Chart
With ch 'shape.chart'
.SetSourceData Union(rs, Range(Cells(2, i), Cells(21, i)))
.HasTitle = True
.ChartTitle.Text = ws.Range("T1")
.HasLegend = True
End With
With sh
.Name = "cht" & (i - 19)
.Top = (i - 20) * rd.Height
.Left = rd.Left
.Width = rd.Width
.Height = rd.Height
End With
Next i
End Sub
Sub diameter()
Dim ws As Worksheet
Dim sh As Shape
Dim ch As Chart
Dim rng As Range, rngTime As Range
Dim n As Integer, m As Integer, k As Integer, i As Integer
Set ws = Sheets("S1")
'delete previous plots
If ws.ChartObjects.Count > 0 Then
ws.ChartObjects.Delete
End If
Set rngTime = ws.Range(Cells(2, 19), Cells(21, 19))
ws.Shapes.AddChart2(240, xlXYScatterLines).Select
ws.Shapes(1).Chart.SetSourceData Union(rngTime, Range(Cells(2, 20), Cells(21, 20)))
'Source:=Range("'S1'!$S$2:$S$21,'S1'!$T$2:$T$21")
For n = 1 To 20
m = n * 20
With ActiveChart.SeriesCollection.NewSeries
ActiveChart.FullSeriesCollection(n).XValues = ws.Range(Cells(2, 19), Cells(21, 19))
ActiveChart.FullSeriesCollection(n).Values = ws.Range(Cells(m - 18, 20), Cells(m + 1, 20))
End With
Next n
End Sub
'''
Related
I need the expert help in VBA Excel code. I need to find the number of duplicate record (AlertToString) for particular device serial number from the source sheet serial number and paste it to the other newly created output sheet by using VBA Macro.
Example (Source sheet):
Expected (Output Sheet with repeat Alert count) :
Source code as below :
Sub Alert700Count()
Dim AlertSource_Sh As Worksheet
Dim AlertOutput_Sh As Worksheet
'Insert a New Blank Worksheet
On Error Resume Next
Application.DisplayAlerts = False
Worksheets("AlertOutput").Delete
Sheets.Add.Name = "AlertOutput"
Application.DisplayAlerts = True
Set AlertSource_Sh = ThisWorkbook.Sheets("SourceSheet")
Set AlertOutput_Sh = ThisWorkbook.Sheets("AlertOutput")
AlertOutput_Sh.Cells(1, 1) = "Serial No"
AlertOutput_Sh.Cells(1, 2) = "A92"
AlertOutput_Sh.Cells(1, 3) = "A95"
AlertOutput_Sh.Cells(1, 4) = "A98"
For Each sh In ActiveWorkbook.Worksheets
With sh.Range("A1:D1")
.Font.Bold = True
.WrapText = True
.CellWidth = 35
.Selection.Font.ColorIndex = 49
.Weight = xlMedium
.LineStyle = xlDash
End With
Next sh
AlertOutput_Sh.Range("A1:D1").Borders.Color = RGB(10, 201, 88)
AlertOutput_Sh.Columns("A:D").ColumnWidth = 12
AlertOutput_Sh.Range("A1:D1").Font.Color = rgbBlueViolet
AlertOutput_Sh.Range("A1:D1").Interior.Color = vbYellow
AlertOutput_Sh.Range("A1:D1").HorizontalAlignment = xlCenter
AlertOutput_Sh.Range("A1:D1").VerticalAlignment = xlTop
' Search the duplicate record and paste in output sheet
Dim A92Count As Long
A92Count = Application.CountIf(AlertSource_Sh.Range("D:D"), "A92")
AlertOutput_Sh.Cells(2, 2) = A92Count
Dim A95Count As Long
A95Count = Application.CountIf(AlertSource_Sh.Range("D:D"), "A95")
AlertOutput_Sh.Cells(2, 3) = A92Count
Dim A98Count As Long
A98Count = Application.CountIf(AlertSource_Sh.Range("D:D"), "A98")
AlertOutput_Sh.Cells(2, 4) = A98Count
End Sub
Current Output :
Use Dictionaries to build lists of unique values and an array to hold the counts.
Option Explicit
Sub Alert700Count()
Dim wsData As Worksheet, wsOut As Worksheet
Dim dictSerNo As Object, dictAlert As Object
Dim arData, arOut, k, rngOut As Range
Dim lastrow As Long, i As Long
Dim serNo As String, alert As String
Dim r As Long, c As Long, t0 As Single: t0 = Timer
Set dictSerNo = CreateObject("Scripting.Dictionary")
Set dictAlert = CreateObject("Scripting.Dictionary")
On Error Resume Next
Application.DisplayAlerts = False
Sheets("AlertOutput").Delete
Application.DisplayAlerts = True
On Error GoTo 0
Sheets.Add.Name = "AlertOutput"
Set wsOut = Sheets("AlertOutput")
Set wsData = Sheets("SourceSheet")
r = 1: c = 1
With wsData
lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row
arData = .Range("A1:D" & lastrow).Value2
' get unique serno and alert
For i = 2 To lastrow
serNo = arData(i, 1)
alert = arData(i, 4)
If dictSerNo.exists(serNo) Then
ElseIf Len(serNo) > 0 Then
r = r + 1
dictSerNo.Add serNo, r
End If
If dictAlert.exists(alert) Then
ElseIf Len(alert) > 0 Then
c = c + 1
dictAlert.Add alert, c
End If
Next
' rescan for counts
ReDim arOut(1 To r, 1 To c)
For i = 2 To lastrow
r = dictSerNo(CStr(arData(i, 1)))
c = dictAlert(CStr(arData(i, 4)))
arOut(r, c) = arOut(r, c) + 1
Next
End With
' add headers
arOut(1, 1) = "Serial No"
' sernos and alerts
For Each k In dictSerNo
arOut(dictSerNo(k), 1) = k
Next
For Each k In dictAlert
arOut(1, dictAlert(k)) = k
Next
' output counts
With wsOut
Set rngOut = .Range("A1").Resize(UBound(arOut), UBound(arOut, 2))
rngOut.Value2 = arOut
rngOut.Replace "", 0
.ListObjects.Add(xlSrcRange, rngOut, , xlYes).Name = "Table1"
.Range("A1").AutoFilter
.Range("A1").Select
End With
MsgBox "Done", vbInformation, Format(Timer - t0, "0.0 secs")
End Sub
I have a worksheet with about 30 charts I want to update dynamically with a VBA macro. I have some issues in handling the series, but I can't find out what's wrong.
The code should run through several charts (only 3 in the following code), clear old contents, and add 6 new series with data taken from the spreadsheet. On the contrary, it doesn't delete the old series and, at each run, adds them again with a new one, then quits with a "Parameter not valid" error on line 22. I have been struggling on this for a couple of weeks now, and the most frustrating part is that the code is basically a copy+paste from another project, which works fine.
Here's the code:
Public Sub Refresh_NB_Graphs()
Dim cht As Chart
Dim chtObj As ChartObject
Dim vi As Integer
Dim s As Object
Dim j As Integer
Dim k As Integer
Dim seriesIndex As Integer
Dim xRange As Range
Dim yRange As Range
'Application.ScreenUpdating = False
On Error GoTo Errorcatch
'Graph fetching and update cycle
For vi = 1 To 3
Set chtObj = Sh_NBGain.ChartObjects("Ch_Gain_Vs" & CStr(vi))
Set cht = chtObj.Chart
' Adding or removing this section makes no difference -------
For Each s In cht.SeriesCollection
s.Delete
Next s
' -----------------------------------------------------------
cht.ChartArea.ClearContents
'Format Font Type and Size
cht.ChartType = xlXYScatterLinesNoMarkers ' scatter plot
cht.ChartArea.Format.TextFrame2.TextRange.Font.Name = "Arial"
cht.ChartArea.Format.TextFrame2.TextRange.Font.Size = 14
cht.HasTitle = False ' No chart title
' Add series: data origin in Sh_NBGainProcess
seriesIndex = 0
For j = 0 To 5
seriesIndex = seriesIndex + 1
cht.SeriesCollection.NewSeries
1 cht.SeriesCollection(seriesIndex).Name = CStr(Sh_Vars.Range("A8").Offset(j, 0).Value)
Set xRange = Sh_NBGainProcess.Range("C42:C1642").Offset(1600 * (vi - 1), 20 * j)
Set yRange = Sh_NBGainProcess.Range("D42:D1642").Offset(1600 * (vi - 1), 20 * j)
10 cht.SeriesCollection(seriesIndex).XValues = "='" & Sh_NBGainProcess.Name & "'!" & xRange.Address
20 cht.SeriesCollection(seriesIndex).Values = "='" & Sh_NBGainProcess.Name & "'!" & yRange.Address
22 With cht.SeriesCollection(seriesIndex)
23 Debug.Print seriesIndex
30 .Format.Line.Weight = 2.25
40 .Format.Line.Visible = msoTrue
50 .Format.Line.ForeColor.RGB = ECOPalette(j) ' Array with defined colors
60 .MarkerStyle = xlMarkerStyleNone
End With
Next j
'.....................
Next vi
End Sub
Can anybody help?
Thanks!
Had to rework the code a bit, but now it's fine:
Dim cht As Chart
Dim s As Series
Dim vi As Integer
Dim j As Integer
Dim xRange As Range
Dim yRange As Range
'Application.ScreenUpdating = False
On Error GoTo Errorcatch
'Graph fetching and update cycle
For vi = 1 To 3
' Gain charts (Vs 1 to 3) ***********************************************************************************************************
Set cht = Sh_NBGain.ChartObjects("Ch_Gain_Vs" & CStr(vi)).Chart
' Clear existing data
For Each s In cht.SeriesCollection
s.Delete
Next s
cht.ChartArea.ClearContents
cht.ChartType = xlXYScatterLinesNoMarkers ' scatter plot
' Add series: data origin in Sh_NBGainProcess
For j = 0 To 5
If Not Sh_NBGainProcess.Range("C42").Offset(1601 * (vi - 1), 20 * j).Value = "" Then
10 Set s = cht.SeriesCollection.NewSeries
40 s.Name = CStr(Sh_Vars.Range("A8").Offset(j, 0).Value)
50 Set xRange = Sh_NBGainProcess.Range("C42:C1642").Offset(1601 * (vi - 1), 20 * j)
60 Set yRange = Sh_NBGainProcess.Range("D42:D1642").Offset(1601 * (vi - 1), 20 * j)
90 s.XValues = "='" & Sh_NBGainProcess.Name & "'!" & xRange.Address
100 s.Values = "='" & Sh_NBGainProcess.Name & "'!" & yRange.Address
110 With s
130 .Format.Line.Weight = 2.25
140 .Format.Line.Visible = msoTrue
150 .Format.Line.ForeColor.RGB = ECOPalette(j)
160 .MarkerStyle = xlMarkerStyleNone
End With
End If
Next j
I think that the main issue was due to the use of the series collection indexing, which was somehow misbehaving (I still don't understand why). By referring directly to the series object when created, with Set s = cht.SeriesCollection.NewSeries, things go fine.
I am new to VBA. i have created triangles which i need to place into the 1st empty row above the given data.
Eg: Please Refer the image.
1) Output after running below code. Yellow marked lines is the row where the output should be shown.
2) actual output it should look like this . (I have edited it manually )
I have created triangle for every data in column c. which i have matched to RANGE(I4:AK4),
but as you can see in image, i am getting output in row 13 in actual it should be in empty row.
It is just my idea: As empty row should be used as the output for the given below data.
For Eg: ROW 20 should be used as output row for given below data in column C (C21,C22,C23)
Please refer the code below as i have tried to create triangle but not able to move to 1st empty row to given below data.
Sub addshape()
Dim lastrow As Long
Dim lastCol As Long
Dim heightCell As Long
Dim widthCell As Long
Dim R As Excel.Range
Dim i As Long
Dim l As Long
Dim s As Shape
With ThisWorkbook.Sheets("Tabelle1")
lastrow = .Cells(Rows.Count, 2).End(xlUp).Row
lastCol = .Cells(4, Columns.Count).End(xlToLeft).Column
For i = 6 To lastrow
If .Cells(i, 3) = " " Then
Else
Set R = .Range(.Cells(4, 9), .Cells(4, lastCol))
If IsEmpty(.Cells(i, 3).Value) = False Then
Set s = ActiveSheet.Shapes.addshape(msoShapeIsoscelesTriangle, 51, 220, 14, 12)
With s
.Name = "triangle" & i
.Rotation = 180
.TextFrame.Characters.Text = Cells(i, 2)
.TextFrame.Characters.Font.Size = 10
.TextFrame.Characters.Font.Color = RGB(0, 0, 0)
.TextFrame.VerticalAlignment = xlVAlignCenter
.TextFrame.HorizontalAlignment = xlHAlignCenter
.Line.Weight = 1
.Line.ForeColor.RGB = RGB(0, 0, 0)
.TextEffect.Alignment = msoTextEffectAlignmentCentered
.TextFrame.Orientation = msoTextOrientationHorizontal
.TextFrame.VerticalOverflow = xlOartVerticalOverflowOverflow
.Fill.ForeColor.RGB = RGB(245, 144, 66)
End With
s.Left = 10
l = Application.WorksheetFunction.Match(.Cells(i, 3), R, 0)
l = R(1, l).Left
l = l + (R(1, l).Width / 24)
s.Left = l
End If
End If
Next i
End With
End Sub
Please share your ideas or your codes.
Will be thankful.
What you can do is loop over all your cells backwards to find the first blank cell above the cell you're working from. Then Align the top to the found cell. Concept:
j = i 'Using a new variable to start from i so to not mess up variable i.
Set A = .Range("B1") 'set a range as a blank range will throw an error when used.
Do Until A = "" 'loop until A is assigned a blank cell
j = j - 1 'step -1 to loop backwards
Set A = .Cells(j, 3) 'assign cell to A as one above the last one.
Loop
s.Top = A.Top 'align top of shape to top of found cell.
In your code this would look like so:
Sub addshape()
Dim lastrow As Long
Dim lastCol As Long
Dim heightCell As Long
Dim widthCell As Long
Dim R As Excel.Range
Dim i As Long
Dim j As Long
Dim l As Long
Dim s As Shape
Dim A As Range
With ThisWorkbook.Sheets("Tabelle1")
lastrow = .Cells(Rows.Count, 2).End(xlUp).Row
lastCol = .Cells(4, Columns.Count).End(xlToLeft).Column
For i = 6 To lastrow
If .Cells(i, 3) = " " Then
Else
Set R = .Range(.Cells(4, 9), .Cells(4, lastCol))
If IsEmpty(.Cells(i, 3).Value) = False Then
Set s = ActiveSheet.Shapes.addshape(msoShapeIsoscelesTriangle, 51, 220, 14, 12)
With s
.Name = "triangle" & i
.Rotation = 180
.TextFrame.Characters.Text = Cells(i, 2)
.TextFrame.Characters.Font.Size = 10
.TextFrame.Characters.Font.Color = RGB(0, 0, 0)
.TextFrame.VerticalAlignment = xlVAlignCenter
.TextFrame.HorizontalAlignment = xlHAlignCenter
.Line.Weight = 1
.Line.ForeColor.RGB = RGB(0, 0, 0)
.TextEffect.Alignment = msoTextEffectAlignmentCentered
.TextFrame.Orientation = msoTextOrientationHorizontal
.TextFrame.VerticalOverflow = xlOartVerticalOverflowOverflow
.Fill.ForeColor.RGB = RGB(245, 144, 66)
End With
s.Left = 10
l = Application.WorksheetFunction.Match(.Cells(i, 3), R, 0)
l = R(1, l).Left
l = l + (R(1, l).Width / 24)
s.Left = l
j = i
Set A = .Range("B1")
Do Until A = ""
j = j - 1
Set A = .Cells(j, 3)
Loop
s.Top = A.Top
End If
End If
Next i
End With
End Sub
I'm currently working on a project which needs to build graph regarding to a table of analyses to check if the products work with time.
The user starts to choose which products he want to check and the code create a table regarding that.
The two main values are the date and the result which need to be on the graph and the third one is the batch number which needs to be the name of each chart series.
After that the code creates a 2D array with the table.
For Each elementReo In Range("tabReorganize[Date]")
ReDim Preserve tabReo(2, r)
tabReo(0, r) = elementReo
tabReo(1, r) = 0 & elementReo.Offset(0, 1)
tabReo(2, r) = elementReo.Offset(0, 2)
r = r + 1
Next elementReo
And after that I want to create the graph regarding to the number of different batch number that I have.
'This part create the Chart and set the title
Set ChartObj = ActiveSheet.ChartObjects.Add(Left:=2979.75, Width:=550, Top:=358.5, Height:=325)
ChartObj.Chart.ChartType = xlLine
ChartObj.Chart.SetElement (msoElementChartTitleAboveChart)
ChartObj.Chart.ChartTitle.Text = "Humidite"
Dim tabNBN() As String
Dim NBN As Integer
Dim checkNBN As Boolean
ReDim tabNBN(NBN)
Dim SeriesI As Integer
NBN = 0
SeriesI = 0
'Add value in tabNBN regarding to the number of different batch number
For r2 = 0 To r - 1 Step 1
checkNBN = False
For Each elementNBN In tabNBN
If elementNBN = tabReo(1, r2) Then
checkNBN = True
End If
Next elementNBN
If checkNBN = False Then
ReDim Preserve tabNBN(NBN)
tabNBN(NBN) = tabReo(1, r2)
NBN = NBN + 1
End If
Next r2
So I need something to add the series regarding of the number of different batch number and insert the value and the date there.
I'm a beginner with charts in VBA.
if my understanding of the objective is correct then congratulation for a good & challenging question. Assuming the objective is to create a single chart with multiple series representing each batch listed in the range. If assumed result is like the following
then may try the test code (obviously after modifying the range, sheet etc to requirement). The code used Dictionary object, so please add Tools-> Reference to "Microsoft Scripting Runtime". Though I am not fully satisfied with the code regarding some multiple looping etc (degrading the performance) but would work OK with normal data assuming 100/200 rows. I invite experts response for more efficient code in this regard
Option Explicit
Sub test3()
Dim Cht As Chart, ChartObj As ChartObject
Set ChartObj = ActiveSheet.ChartObjects.Add(Left:=10, Width:=550, Top:=10, Height:=325)
'Set ChartObj = ActiveSheet.ChartObjects("Chart 4")
Set Cht = ChartObj.Chart
Cht.ChartType = xlLine
Cht.HasTitle = True
Cht.ChartTitle.Text = "Humidite"
Dim Rw As Long, Dic As Dictionary, DataArr As Variant, OutArr() As Variant, BatchArr() As Variant, DateArr As Variant
Dim Rng As Range, SeriesNo As Long, Dmax As Date, Dmin As Date, dt As Date
Dim X As Long, i As Long, Xbatch As Variant, Batch As Variant
Dim Cnt As Long, Xval As Variant, PrvDt As Date, C As Range, DayCnt As Long
Dim firstAddress As String
Set Dic = CreateObject("Scripting.dictionary")
Set Rng = ThisWorkbook.ActiveSheet.Range("A2:A100") 'Modify to requireMent
DataArr = ThisWorkbook.ActiveSheet.Range("A2:C100") 'Modify to requireMent
SeriesNo = 0
'Create dictionary reference to unique Batch name from the list
For Rw = 1 To UBound(DataArr, 1)
Batch = DataArr(Rw, 2)
If Dic.Exists(Batch) = False Then
SeriesNo = SeriesNo + 1
Dic.Add Batch, SeriesNo
End If
Next
Dmax = Application.WorksheetFunction.Max(Range(Rng(1, 1), Rng(Rng.Rows.Count, 1)))
Dmin = Application.WorksheetFunction.Min(Range(Rng(1, 1), Rng(Rng.Rows.Count, 1)))
DayCnt = Dmax - Dmin + 1
ReDim BatchArr(1 To DayCnt)
ReDim DateArr(1 To DayCnt)
ReDim OutArr(1 To SeriesNo, 1 To DayCnt)
'Populate DateArr for dates
For X = 1 To DayCnt
DateArr(X) = Dmin + X - 1
Next
'Populate OutArr(Series,DayCnt) with existing Values, Non existing values are kept empty
For X = 1 To DayCnt
dt = DateArr(X)
With Rng
Set C = .Find(dt)
If Not C Is Nothing Then
firstAddress = C.Address
Do
OutArr(Dic(C.Offset(0, 1).Value), X) = C.Offset(0, 2).Value
'Debug.Print C.Value, C.Offset(0, 1).Value, C.Offset(0, 2).Value
Set C = .FindNext(C)
Loop While Not C Is Nothing And C.Address <> firstAddress
End If
End With
Next
With Cht
'delete If any automatically added series
For i = Cht.SeriesCollection.Count To 1 Step -1
.SeriesCollection(i).Delete
Next
'Create Series and Set Values & Xvalues from OutArr
Dim Srs As Series
For X = 1 To SeriesNo
Batch = Dic.Keys(X - 1)
For Cnt = 1 To DayCnt
BatchArr(Cnt) = OutArr(Dic(Batch), Cnt)
'If IsEmpty(BatchArr(Cnt)) = False Then Debug.Print X, Cnt, BatchArr(Cnt), DateArr(Cnt)
Next
Cht.SeriesCollection.NewSeries
Set Srs = Cht.SeriesCollection(X)
With Srs
.Values = BatchArr
.XValues = DateArr
.Name = Dic.Keys(X - 1)
End With
Next
Dim Cat As Axis
Set Cat = Cht.Axes(xlCategory)
Cat.TickLabels.NumberFormat = "dd/mm/yy"
End With
End Sub
Please comment if it suits your need
This code should create a table regarding to another table (the one with all different batch numbers and values) and the user selection and after build the chart with it.
I can send you the full file by mail if needed.
Thanks in advance.
Best regards
colin
Private Sub BtnGraph2_Click()
Dim tabBNumber() As String
Dim tabHumidite() As Double
Dim tabDate() As String
Dim tabReo() As String
Dim y As Integer
Dim h As Integer
Dim d As Integer
Dim a As Integer
Dim w As Integer
Dim w2 As Integer
Dim r As Integer
h = 0
y = 0
d = 0
w = 1
w2 = 1
r = 0
ReDim tabHumidite(h)
ReDim tabBNumber(y)
ReDim tabDate(d)
Range("tabReorganize[#data]") = ""
ListObjects("tabReorganize").Resize Range(Range("tabReorganize[#headers]").Address, Range("tabReorganize[#headers]").Offset(1).Address)
For i6 = ListBox1.ListCount - 1 To 0 Step -1
If ListBox1.Selected(i6) = True Then
ReDim Preserve tabBNumber(y)
tabBNumber(y) = ListBox1.List(i6)
y = y + 1
End If
Next i6
For Each delement In tabBNumber
For Each delement2 In Range("tabGraph[Date]")
If "0" & delement2.Offset(0, 2) = delement Or delement2.Offset(0, 2) = delement Then
ReDim Preserve tabDate(d)
tabDate(d) = delement2
d = d + 1
End If
Next delement2
Next delement
For Each Oelement In tabDate
Range("tabReorganize[Date]").Cells(w) = Format(Oelement, "mm/dd/yyyy")
w = w + 1
Next Oelement
If BtnHumidite = True Then
For Each element In tabBNumber
h = 0
a = 0
ReDim tabHumidite(h)
For Each Gelement In Range("tabGraph[Humidite]")
If "0" & Gelement.Offset(0, -1) = element Or Gelement.Offset(0, -1) = element Then
ReDim Preserve tabHumidite(h)
tabHumidite(h) = Gelement
h = h + 1
End If
Next Gelement
For Each O2element In tabHumidite
Range("tabReorganize[Humidite]").Cells(w2) = Format(O2element, "###0.00")
Range("tabReorganize[Batch Number]").Cells(w2) = Format(element, "00000000")
w2 = w2 + 1
Next O2element
Next element
End If
Range("tabReorganize").Sort Key1:=Range("tabReorganize[[#All],[Date]]"), Order1:=xlAscending, Header:=xlYes
For Each elementReo In Range("tabReorganize[Date]")
ReDim Preserve tabReo(2, r)
tabReo(0, r) = elementReo
tabReo(1, r) = 0 & elementReo.Offset(0, 1)
tabReo(2, r) = elementReo.Offset(0, 2)
r = r + 1
Next elementReo
'''' Chart part
Dim Cht As Chart, ChartObj As ChartObject
Set ChartObj = ActiveSheet.ChartObjects.Add(Left:=2979.75, Width:=550, Top:=358.5, Height:=325)
Set Cht = ChartObj.Chart
Cht.ChartType = xlLine
Cht.HasTitle = True
Cht.ChartTitle.Text = "Humidite"
Dim Rw As Long, Dic As Dictionary, DataArr As Variant, OutArr() As Variant, BatchArr() As Variant, DateArr As Variant
Dim Rng As Range, SeriesNo As Long, Dmax As Date, Dmin As Date, dt As Date
Dim X As Long, i As Long, Xbatch As Variant, Batch As Variant
Dim Cnt As Long, Xval As Variant, PrvDt As Date, C As Range, DayCnt As Long
Dim firstAddress As String
Set Dic = CreateObject("Scripting.dictionary")
Set Rng = ThisWorkbook.ActiveSheet.Range("AP13:AP42") 'Modify to requireMent
'Set Rng = ThisWorkbook.ActiveSheet.Range("tabReorganize[Date]")
DataArr = ThisWorkbook.ActiveSheet.Range("AP13:AR42") 'Modify to requireMent
'DataArr = ThisWorkbook.ActiveSheet.Range("tabReorganize[#data]")
SeriesNo = 0
'Create dictionary reference to unique Batch name from the list
For Rw = 1 To UBound(DataArr, 1)
Batch = DataArr(Rw, 2)
If Dic.Exists(Batch) = False Then
SeriesNo = SeriesNo + 1
Dic.Add Batch, SeriesNo
End If
Next
Dmax = Application.WorksheetFunction.max(Range(Rng(1, 1), Rng(Rng.Rows.Count, 1)))
Dmin = Application.WorksheetFunction.Min(Range(Rng(1, 1), Rng(Rng.Rows.Count, 1)))
DayCnt = Dmax - Dmin + 1
ReDim BatchArr(1 To DayCnt)
ReDim DateArr(1 To DayCnt)
ReDim OutArr(1 To SeriesNo, 1 To DayCnt)
'Populate DateArr for dates
For X = 1 To DayCnt
DateArr(X) = Dmin + X - 1
Next
'Populate OutArr(Series,DayCnt) with existing Values, Non existing values are kept empty
For X = 1 To DayCnt
dt = DateArr(X)
With Rng
Set C = .Find(dt)
If Not C Is Nothing Then
firstAddress = C.Address
Do
OutArr(Dic(C.Offset(0, 1).Value), X) = C.Offset(0, 2).Value
'Debug.Print C.Value, C.Offset(0, 1).Value, C.Offset(0, 2).Value
Set C = .FindNext(C)
Loop While Not C Is Nothing And C.Address <> firstAddress
End If
End With
Next
With Cht
'delete If any automatically added series
For i = Cht.SeriesCollection.Count To 1 Step -1
.SeriesCollection(i).Delete
Next
'Create Series and Set Values & Xvalues from OutArr
Dim Srs As Series
For X = 1 To SeriesNo
Batch = Dic.Keys(X - 1)
For Cnt = 1 To DayCnt
BatchArr(Cnt) = OutArr(Dic(Batch), Cnt)
'If IsEmpty(BatchArr(Cnt)) = False Then Debug.Print X, Cnt, BatchArr(Cnt), DateArr(Cnt)
Next
Cht.SeriesCollection.NewSeries
Set Srs = Cht.SeriesCollection(X)
With Srs
.Values = BatchArr
.XValues = DateArr
.Name = Dic.Keys(X - 1)
End With
Next
Dim Cat As Axis
Set Cat = Cht.Axes(xlCategory)
Cat.TickLabels.NumberFormat = "mm/dd/yy"
End With
I have a problem with my macro that creates chart, it works well when I step through but restarts my Excel when I run it normally. Tried various things, nothing works. It was originally part of other macro, but I isolated it to another sub, thinking it may help, but it still crashes when isolated.
Do you guys know what may be causing this?
EDIT1: There is no error information, the excel just restarts
EDIT2: The problem seems to be caused by this part of code:
.SetElement (msoElementChartTitleAboveChart)
.ChartTitle.Text = "Liczba Dni Promocji - Wykres"
.ChartTitle.Font.Bold = True
.ChartTitle.Font.Size = 16
This is the code:
Sub StworzWykres()
Application.ScreenUpdating = False
'Application.PrintCommunication = True
Dim ws As Worksheet
Dim pt As PivotTable
Dim chrt As Chart
Dim myRng As Range
Dim i As Integer
Dim j As Integer
Set ws = ThisWorkbook.Sheets("Raport_LiczbaDniPromocji")
Set pt = ws.PivotTables("LDP_Tab1")
'delete existing charts
Dim shp As Shape
For Each shp In ws.Shapes
shp.Delete
Next shp
Set shp = Nothing
'ask if make a chart
Application.ScreenUpdating = True
If MsgBox("Czy chcesz utworzyć wykres Liczby Dni Promocji?", vbYesNo, "Wykres") = vbNo Then
Exit Sub
End If
Application.ScreenUpdating = False
'adding the chart
'Set chrt = ws.Shapes.AddChart.Chart
Set myRng = ws.Range(Cells(19 + pt.RowRange.Rows.Count, 4), Cells(18 + 2 * (pt.RowRange.Rows.Count), 6))
myRng.Select
Set chrt = ws.Shapes.AddChart.Chart
'Set chrt = ws.ChartObjects.Add.Chart
'chrt.Activate
With chrt
'For j = .SeriesCollection.Count To 1 Step -1
' .SeriesCollection(j).Delete
'Next j
'.SetSourceData Source:=myRng, PlotBy:=xlColumns
.ChartType = xl3DColumnClustered
'.SetSourceData Source:=myRng, PlotBy:=xlColumns
.Parent.Name = "Wykres_LDP"
.DepthPercent = 400
.PlotArea.Format.ThreeD.RotationX = 0
.PlotArea.Format.ThreeD.RotationY = 110
.RightAngleAxes = True
.ChartArea.Left = ws.Range(Cells(1, 1), Cells(1, 6)).Width + 1 'ws.Cells(20 + pt.RowRange.Rows.Count, 8).Left - (ws.Columns(7).ColumnWidth / 1.25)
.ChartArea.Top = ws.Cells(18 + pt.RowRange.Rows.Count, 8).Top
.ChartArea.Height = ws.Range(Cells(19 + pt.RowRange.Rows.Count, 8), Cells(47 + pt.RowRange.Rows.Count, 8)).Height
.ChartArea.Width = 1000
.Parent.Placement = xlMove
.ChartColor = 10
.ChartGroups(1).GapWidth = 150
.SetElement (msoElementLegendBottom)
.Legend.Font.Size = 12
.Legend.Font.Bold = True
.SetElement (msoElementChartTitleAboveChart)
.ChartTitle.Text = "Liczba Dni Promocji - Wykres"
.ChartTitle.Font.Bold = True
.ChartTitle.Font.Size = 16
With .Axes(xlCategory, xlPrimary)
.TickLabels.Orientation = 60
'.TickLabels.Font.Bold = True
'.TickLabels.Font.Size = 11
End With
For j = .SeriesCollection.Count To 1 Step -1
.SeriesCollection(j).HasDataLabels = True
.SeriesCollection(j).DataLabels.Orientation = xlUpward
.SeriesCollection(j).DataLabels.Font.Bold = True
.SeriesCollection(j).DataLabels.Font.Size = 10
If j = 1 Then
.SeriesCollection(j).DataLabels.Font.ColorIndex = 32
Else
.SeriesCollection(j).DataLabels.Font.ColorIndex = 46
End If
Next j
'.SetSourceData Source:=myRng, PlotBy:=xlColumns
End With
'clear variables
Set ws = Nothing
Set pt = Nothing
Set myRng = Nothing
i = Empty
j = Empty
'Application.PrintCommunication = False
Application.ScreenUpdating = True
End Sub
Remove
.SetElement (msoElementChartTitleAboveChart)
and insert
.HasTitle = True
in the same place.