This is a rough sample but shows most of the things I think. You need the header file. I hope you have it or could create using utilities like Westwind's GetConstants. Be notified some options are only applicable to 3d charts and no extra error checking, notifying. oForm=createobject('form1') oForm.Show Read events #INCLUDE "mschrt20.h" Define CLASS form1 AS form Top = 0 Left = 0 Height = 574 Width = 784 DoCreate = .T. Caption = "Try to click, drag with Ctrl+Button or button alone" Name = "Form1" Add OBJECT mschart AS olecontrol WITH ; Top = 5, ; Left = 2, ; Height = 451, ; Width = 778, ; Name = "MsChart", ; OleClass = 'MSChart20Lib.MsChart' Add OBJECT command1 AS commandbutton WITH ; Top = 466, ; Left = 220, ; Height = 27, ; Width = 102, ; Caption = "Data from array", ; Name = "Command1" Add OBJECT command2 AS commandbutton WITH ; Top = 466, ; Left = 89, ; Height = 27, ; Width = 127, ; Caption = "Multiply data with 10", ; Name = "Command2" Add OBJECT command3 AS commandbutton WITH ; Top = 466, ; Left = 325, ; Height = 27, ; Width = 84, ; Caption = "Random data", ; Name = "Command3" Add OBJECT command4 AS commandbutton WITH ; Top = 466, ; Left = 411, ; Height = 27, ; Width = 110, ; Caption = "Data from cursor", ; Name = "Command4" Add OBJECT command5 AS commandbutton WITH ; Top = 466, ; Left = 3, ; Height = 27, ; Width = 84, ; Caption = "Title on right", ; Name = "Command5" Add OBJECT combo1 AS combobox WITH ; Height = 24, ; Left = 72, ; Top = 504, ; Width = 156, ; DisabledItemBackColor = RGB(192,192,192), ; DisabledItemForeColor = RGB(128,128,128), ; Name = "Combo1" Add OBJECT combo2 AS combobox WITH ; Height = 24, ; Left = 72, ; Top = 530, ; Width = 156, ; Name = "Combo2" Add OBJECT label1 AS label WITH ; Caption = "Perspective", ; Height = 17, ; Left = -1, ; Top = 535, ; Width = 72, ; Name = "Label1" Add OBJECT label2 AS label WITH ; Caption = "Chart Type", ; Height = 17, ; Left = 7, ; Top = 507, ; Width = 61, ; Name = "Label2" Add OBJECT label3 AS label WITH ; Caption = "Elevation", ; Height = 17, ; Left = 235, ; Top = 508, ; Width = 60, ; Name = "Label3" Add OBJECT label4 AS label WITH ; Caption = "Rotation", ; Height = 17, ; Left = 235, ; Top = 529, ; Width = 48, ; Name = "Label4" Add OBJECT spinner1 AS spinner WITH ; Height = 24, ; KeyboardHighValue = 90, ; KeyboardLowValue = 0, ; Left = 288, ; SpinnerHighValue = 90.00, ; SpinnerLowValue = 0.00, ; Top = 503, ; Width = 53, ; Value = 30, ; Name = "Spinner1" Add OBJECT spinner2 AS spinner WITH ; Height = 24, ; Increment = 10.00, ; KeyboardHighValue = 360, ; KeyboardLowValue = 0, ; Left = 288, ; SpinnerHighValue = 360.00, ; SpinnerLowValue = 0.00, ; Top = 528, ; Width = 53, ; Name = "Spinner2" Add OBJECT label5 AS label WITH ; AutoSize = .T., ; Caption = "DepthToHeightRatio", ; Height = 17, ; Left = 468, ; Top = 504, ; Width = 114, ; Name = "Label5" Add OBJECT label6 AS label WITH ; Caption = "WidthToHeightRatio", ; Height = 17, ; Left = 468, ; Top = 528, ; Width = 112, ; Name = "Label6" Add OBJECT label7 AS label WITH ; Caption = "xGap", ; Height = 17, ; Left = 348, ; Top = 507, ; Width = 36, ; Name = "Label7" Add OBJECT label8 AS label WITH ; Caption = "zGap", ; Height = 17, ; Left = 348, ; Top = 528, ; Width = 36, ; Name = "Label8" Add OBJECT spinner3 AS spinner WITH ; Height = 24, ; Increment = 10.00, ; KeyboardHighValue = 100, ; KeyboardLowValue = 0, ; Left = 384, ; SpinnerHighValue = 100.00, ; SpinnerLowValue = 0.00, ; Top = 504, ; Width = 71, ; Name = "Spinner3" Add OBJECT spinner4 AS spinner WITH ; Height = 24, ; Increment = 10.00, ; KeyboardHighValue = 100, ; KeyboardLowValue = 0, ; Left = 384, ; SpinnerHighValue = 100.00, ; SpinnerLowValue = 0.00, ; Top = 529, ; Width = 71, ; Name = "Spinner4" Add OBJECT spinner5 AS spinner WITH ; Height = 24, ; KeyboardHighValue = 10, ; KeyboardLowValue = 1, ; Left = 586, ; SpinnerHighValue = 10.00, ; SpinnerLowValue = 1.00, ; Top = 499, ; Width = 40, ; Name = "Spinner5" Add OBJECT spinner6 AS spinner WITH ; Height = 24, ; KeyboardHighValue = 10, ; KeyboardLowValue = 1, ; Left = 586, ; SpinnerHighValue = 10.00, ; SpinnerLowValue = 1.00, ; Top = 524, ; Width = 40, ; Name = "Spinner6" Procedure Init ColorsMax=3 Dimension colors[3] ColorS[1] ='Red' ColorS[2] ='Silver' ColorS[3] ='Black' Rand(-1) Create cursor comparesales (nyear i, qtr i, car c(10), color c(10)) For years = 1998 to 2000 For iQtr = 1 to 4 For Sales = 1 to 10 Insert into comparesales ; values (years, iQtr, ; iif(int(rand()*1000)%2=0,'Corvette','Ferrari'), ; colors[int(rand()*ColorsMax)%5+1]) Endfor Endfor Endfor * Our xtabber Select distinct car from comparesales into array arrCars order by car Asort(Colors) Dimension Sales[2+alen(arrCars)*alen(colors)] && 2 for year and qtr Dimension arrStruc[alen(Sales),4] arrStruc = 0 arrStruc[1,1] = 'Year' arrStruc[1,2] = 'I' arrStruc[1,3] = 4 arrStruc[2,1] = 'Qtr' arrStruc[2,2] = 'I' arrStruc[2,3] = 4 For ix=1 to alen(arrCars) For jx = 1 to alen(colors) lnCurFieldNum = (ix-1)*alen(colors)+jx+2 arrStruc[lnCurFieldNum,1] = padr(arrCars[ix],5,'_')+padr(colors[jx],5,'_') arrStruc[lnCurFieldNum,2] = 'I' arrStruc[lnCurFieldNum,3] = 4 Endfor Endfor Create cursor crsXTab from array arrStruc For years = 1998 to 2000 For iQtr = 1 to 4 Sales = 0 m.year = years m.qtr = iQtr Select car,color,cnt(*) as amount ; from comparesales ; group by 1,2 ; where nyear = years and qtr = iQtr ; into cursor crsCounts Scan Store amount to ('m.'+padr(trim(car),5,'_')+padr(trim(color),5,'_')) Endscan Insert into crsXTab from memvar Endfor Endfor Select crsXTab With thisform.mschart && Set Chart parameters using methods. rowLabelCount = 2 columnLabelCount = 2 .rowCount = 3*4 .columnCount = alen(arrCars)*alen(colors) Scan .Row = recno() For ix=3 to fcount() .Column = ix-2 .Data = eval(field(ix)) Endfor Endscan Endwith With thisform.mschart.DataGrid rowLabelCount = 2 columnLabelCount = 2 rowCount = 3*4 ColumnCount = alen(arrCars)*alen(colors) .SetSize(rowLabelCount, columnLabelCount, rowCount, ColumnCount ) && Then assign labels to first Level. For iColors = 1 to columncount .ColumnLabel(iColors, 1) = Colors[(iColors-1)%alen(colors)+1] Endfor For iCars=1 to alen(arrCars) .ColumnLabel((iCars-1)*alen(colors)+1, 2) = arrCars[iCars] Endfor For iQtr = 1 to rowCount .RowLabel(iQtr, 1) = (iQtr-1)%4+1 Endfor For years=1998 to 2000 .RowLabel((years-1998)*4+1, 2) = transform(years) Endfor Endwith Thisform.mschart.ShowLegend = .T. Endproc Procedure command1.Click Dimension arrData(3, 3) arrData(1, 1) = "Jan" && Set the labels in the first series. arrData(2, 1) = "Feb" arrData(3, 1) = "Mar" arrData(1, 2) = 8 arrData(2, 2) = 4 arrData(3, 2) = 0.3 arrData(1, 3) = 0.2 arrData(2, 3) = 3 arrData(3, 3) = 6.3 #Define TABULATE chr(9) #Define CRLF chr(13)+chr(10) m.Str = '' For ix = 1 to 3 For jx = 1 to 3 m.Str = m.Str + transform(arrData[ix,jx])+TABULATE Endfor m.Str = left(m.Str,len(m.Str)-1)+CRLF Endfor _Cliptext = m.Str Thisform.mschart.Editpaste Thisform.mschart.ShowLegend Endproc Procedure command2.Click With thisform.mschart For icolumn = 1 To .ColumnCount For irow = 1 To .rowCount .Column = icolumn .Row = irow .Data = val(.Data) * 10 Endfor Endfor .DataGrid.RowLabel(1,1) = 'Hello' Endwith Endproc Procedure command3.Click With thisform.mschart.DataGrid && Set Chart parameters using methods. rowLabelCount = 2 columnLabelCount = 2 rowCount = 6 ColumnCount = 6 .SetSize(rowLabelCount, columnLabelCount, rowCount, ColumnCount ) && Randomly fill in the data. .RandomDataFill && Then assign labels to second Level. labelIndex = 2 Column = 1 .ColumnLabel(column, labelIndex) = "Product 1" Column = 4 .ColumnLabel(column, labelIndex) = "Product 2" Row = 1 .RowLabel(row, labelIndex) = "1994" .RowLabel(row, 1) = "Dummy label" Row = 4 .RowLabel(row, labelIndex) = "1995" Endwith Thisform.mschart.ShowLegend = .T. Endproc Procedure command4.Click ColorsMax=3 Dimension colors[3] ColorS[1] ='Red' ColorS[2] ='Silver' ColorS[3] ='Black' Rand(-1) Create cursor comparesales (nyear i, qtr i, car c(10), color c(10)) For years = 1998 to 2000 For iQtr = 1 to 4 For Sales = 1 to 10 Insert into comparesales ; values (years, iQtr, ; iif(int(rand()*1000)%2=0,'Corvette','Ferrari'), ; colors[int(rand()*ColorsMax)%5+1]) Endfor Endfor Endfor * Our xtabber Select distinct car from comparesales into array arrCars order by car Asort(Colors) Dimension Sales[2+alen(arrCars)*alen(colors)] && 2 for year and qtr Dimension arrStruc[alen(Sales),4] arrStruc = 0 arrStruc[1,1] = 'Year' arrStruc[1,2] = 'I' arrStruc[1,3] = 4 arrStruc[2,1] = 'Qtr' arrStruc[2,2] = 'I' arrStruc[2,3] = 4 For ix=1 to alen(arrCars) For jx = 1 to alen(colors) lnCurFieldNum = (ix-1)*alen(colors)+jx+2 arrStruc[lnCurFieldNum,1] = padr(arrCars[ix],5,'_')+padr(colors[jx],5,'_') arrStruc[lnCurFieldNum,2] = 'I' arrStruc[lnCurFieldNum,3] = 4 Endfor Endfor Create cursor crsXTab from array arrStruc For years = 1998 to 2000 For iQtr = 1 to 4 Sales = 0 m.year = years m.qtr = iQtr Select car,color,cnt(*) as amount ; from comparesales ; group by 1,2 ; where nyear = years and qtr = iQtr ; into cursor crsCounts Scan Store amount to ('m.'+padr(trim(car),5,'_')+padr(trim(color),5,'_')) Endscan Insert into crsXTab from memvar Endfor Endfor Select crsXTab Browse title 'Data that would be charted' With thisform.mschart && Set Chart parameters using methods. rowLabelCount = 2 columnLabelCount = 2 .rowCount = 3*4 .columnCount = alen(arrCars)*alen(colors) Scan .Row = recno() For ix=3 to fcount() .Column = ix-2 .Data = eval(field(ix)) Endfor Endscan Endwith With thisform.mschart.DataGrid rowLabelCount = 2 columnLabelCount = 2 rowCount = 3*4 ColumnCount = alen(arrCars)*alen(colors) .SetSize(rowLabelCount, columnLabelCount, rowCount, ColumnCount ) && Then assign labels to first Level. For iColors = 1 to columncount .ColumnLabel(iColors, 1) = Colors[(iColors-1)%alen(colors)+1] Endfor For iCars=1 to alen(arrCars) .ColumnLabel((iCars-1)*alen(colors)+1, 2) = arrCars[iCars] Endfor For iQtr = 1 to rowCount .RowLabel(iQtr, 1) = (iQtr-1)%4+1 Endfor For years=1998 to 2000 .RowLabel((years-1998)*4+1, 2) = transform(years) Endfor Endwith Thisform.mschart.ShowLegend = .T. Endproc Procedure command5.Click Thisform.mschart.TitleText = 'Chart Title' With thisform.mschart.Title With .VtFont .Name = "Times New Roman" .Size = 18 .Style = bitor(VtFontStyleBold, VtFontStyleItalic) .Effect = VtFontEffectUnderline .VtColor.Set( 255, 0, 0 ) Endwith .Location.Visible = .T. .Location.LocationType = VtChLocationTypeRight With .TextLayOut .Orientation = VtOrientationUp .HorzAlignment = VtHorizontalAlignmentCenter .VertAlignment = VtVerticalAlignmentCenter Endwith Endwith Endproc Procedure combo1.Init With this .ColumnCount = 2 .Boundcolumn=2 .BoundTo = .t. .ColumnWidths = '100,20' .AddListItem('3dBar',1,1) .AddListItem(transform(VtChChartType3dBar),1,2) .AddListItem('2dBar',2,1) .AddListItem(transform(VtChChartType2dBar),2,2) .AddListItem('3dLine',3,1) .AddListItem(transform(VtChChartType3dLine),3,2) .AddListItem('2dLine',4,1) .AddListItem(transform(VtChChartType2dLine),4,2) .AddListItem('3dArea',5,1) .AddListItem(transform(VtChChartType3dArea),5,2) .AddListItem('2dArea',6,1) .AddListItem(transform(VtChChartType2dArea),6,2) .AddListItem('3dStep',7,1) .AddListItem(transform(VtChChartType3dStep),7,2) .AddListItem('2dStep',8,1) .AddListItem(transform(VtChChartType2dStep),8,2) .AddListItem('3dCombination',9,1) .AddListItem(transform(VtChChartType3dCombination),9,2) .AddListItem('2dCombination',10,1) .AddListItem(transform(VtChChartType2dCombination),10,2) .AddListItem('3dHorizontalBar',11,1) .AddListItem('\'+transform(VtChChartType3dHorizontalBar),11,2) .AddListItem('2dHorizontalBar',12,1) .AddListItem('\'+transform(VtChChartType2dHorizontalBar),12,2) .AddListItem('3dClusteredBar',13,1) .AddListItem('\'+transform(VtChChartType3dClusteredBar),13,2) .AddListItem('3dPie',14,1) .AddListItem('\'+transform(VtChChartType3dPie),14,2) .AddListItem('2dPie',15,1) .AddListItem(transform(VtChChartType2dPie),15,2) .AddListItem('3dDoughnut',16,1) .AddListItem('\'+transform(VtChChartType3dDoughnut),16,2) .AddListItem('2dXY',17,1) .AddListItem(transform(VtChChartType2dXY),17,2) .AddListItem('2dPolar',18,1) .AddListItem('\'+transform(VtChChartType2dPolar),18,2) .AddListItem('2dRadar',19,1) .AddListItem('\'+transform(VtChChartType2dRadar),19,2) .AddListItem('2dBubble',20,1) .AddListItem('\'+transform(VtChChartType2dBubble),20,2) .AddListItem('2dHiLo',21,1) .AddListItem('\'+transform(VtChChartType2dHiLo),21,2) .AddListItem('2dGantt',22,1) .AddListItem('\'+transform(VtChChartType2dGantt),22,2) .AddListItem('3dGantt',23,1) .AddListItem('\'+transform(VtChChartType3dGantt),23,2) .AddListItem('3dSurface',24,1) .AddListItem('\'+transform(VtChChartType3dSurface),24,2) .AddListItem('2dContour',25,1) .AddListItem('\'+transform(VtChChartType2dContour),25,2) .AddListItem('3dScatter',26,1) .AddListItem('\'+transform(VtChChartType3dScatter),26,2) .AddListItem('3dXYZ',27,1) .AddListItem('\'+transform(VtChChartType3dXYZ),27,2) .AddListItem('Count',28,1) .AddListItem('\'+transform(VtChChartTypeCount),28,2) Endwith Endproc Procedure combo1.Valid Thisform.mschart.ChartType = val(this.Value) If val(this.Value) = VtChChartType2dPie For Each serX In ThisForm.mschart.Plot.SeriesCollection With serX.Datapoints.Item(-1).DatapointLabel .Component = VtChLabelComponentPercent && Show as percent .LocationType = VtChLabelLocationTypeInside && Inside pie slice .PercentFormat = '0%' Endwith Endfor Else For Each serX In ThisForm.mschart.Plot.SeriesCollection With serX.Datapoints.Item(-1).DatapointLabel .LocationType = VtChLabelLocationTypeNone && No label Endwith Endfor Endif Endproc Procedure combo2.Valid With thisform.mschart * Set the chart to a 3D type. .ChartType = VtChChartType3dBar * Change the projection when clicked. .Plot.Projection = this.ListIndex-1 Endwith Endproc Procedure combo2.Init With this .AddListItem("VtProjectionTypePerspective") .AddListItem("VtProjectionTypeOblique") .AddListItem("VtProjectionTypeOrthogonal") .AddListItem("VtProjectionTypeFrontal") .AddListItem("VtProjectionTypeOverhead") Endwith Endproc Procedure spinner1.When This.Value = ThisForm.mschart.Plot.View3d.Elevation Endproc Procedure spinner1.InteractiveChange Thisform.mschart.Plot.View3d.Elevation = this.value Endproc Procedure spinner2.When This.Value = ThisForm.mschart.Plot.View3d.Rotation Endproc Procedure spinner2.InteractiveChange Thisform.mschart.Plot.View3d.Rotation = this.value Endproc Procedure spinner3.InteractiveChange Thisform.mschart.Plot.xGap = this.value/100 Endproc Procedure spinner4.InteractiveChange Thisform.mschart.Plot.zGap = this.value/100 Endproc Procedure spinner5.InteractiveChange Thisform.mschart.Plot.DepthToHeightRatio = this.value Endproc Procedure spinner6.InteractiveChange Thisform.mschart.Plot.WidthToHeightRatio = this.value Endproc Procedure queryunload Clear events Endproc Enddefine