* Writer に多系列の散布図 [#l390d6a8]
Calc 以下なのに Writer です。
Writer のチャートは Writer ドキュメント上の表からデータを取得するものと、データを数値で埋め込むものの二種類があります。ここでは後者のデータで指定する方法で行います。
埋め込みドキュメントとしてチャートを作成したら、データを設定します。データは Calc の表で getDataArray メソッドの返り値と同じ並びの二次元配列で指定します。要するに、データは系列とは違うグループで並んでいます。
以下の例では、系列ごとのデータを X、Y データとして配列に入れたものを渡し、行と列を入れ替えてデータに設定します。
データシリーズを作成するときに指定するデータの表現は、Calc では Sheet1.A1:A10 などでしたが、この場合には 0, 1 ... などのようにデータシークエンスのインデックスで指定します (文字列で)。
ラベルはデータプロバイダが保持している ColumnDescriptions から指定します。指定は "label " + インデックスです。このとき、空の要素のインデックスを指定すると作成に失敗するので注意が必要です。
以下の例ではデータ系列を作成する前に ColumnDescriptions を変更しています。特定のラベルを指定したければ適当なところに入れておいて、そのインデックスを指定してください。UI で系列名を変更するとその値が変更されます。
後半の関数については [[OOoBasic/Calc/chart2/ex7]] を参照。
#code(basic){{
Sub InsertChartOnWriterDocumentExample
chart_template = "com.sun.star.chart2.template.ScatterLineSymbol"
' 各配列が X, Y で二系列
data = Array(_
Array(Array(0, 1, 2, 3, 4, 5, 6, 7, 8), Array(10, 11, 13, 14, 12, 13, 10, 8, 7)), _
Array(Array(0.3, 1, 2.1, 3, 4, 4.2, 5.8, 7, 9), Array(10, 13, 16, 18, 13, 14, 15, 10, 19)))
oDoc = ThisComponent
oChart = InsertChartOnWriterDoc(oDoc, chart_template, data)
'mri oChart
End Sub
Function InsertChartOnWriterDoc(doc, template, data)
oText = doc.getText
oChartObj = doc.createInstance("com.sun.star.text.TextEmbeddedObject")
oChartObj.CLSID = "12dcae26-281f-416f-a234-c3086127382e"
oCursor = oText.createTextCursor()
oText.insertTextContent(oCursor, oChartObj, False)
chart = oChartObj.Model
diagram = chart.getFirstDiagram
data_provider = chart.getDataProvider
color_scheme = diagram.getDefaultColorScheme
chart_type_manager = chart.getChartTypeManager
chart_type_template = chart_type_manager.createInstance(template)
chart_type_template.changeDiagram(diagram)
coords = diagram.getCoordinateSystems()
coord = coords(0)
chart_types = coord.getChartTypes()
chart_type = chart_types(0)
data_provider.setData(ExchangeData(data))
n = UBound(data)
Dim series(n)
' ColumnDescriptions の書き換え
Dim columns((n+1)*2-1)
for i = 0 To (n+1) *2 -1 step 1
columns(i) = "Column " & CStr(i)
next
data_provider.setColumnDescriptions(columns)
' 系列を作成
For i = 0 To n step 1
s = create_scatter_series(data_provider, _
CStr(i*2), CStr(i*2+1), "label " & CStr(i*2+1))
s.Color = color_scheme.getColorByIndex(i)
series(i) = s
Next
chart_type.setDataSeries(series)
chart_type_template.changeDiagram(diagram)' # reset
InsertChartOnWriterDoc = chart
End Function
Function create_scatter_series(provider, x_repr, y_repr, Optional label_repr)
series = CreateUnoService("com.sun.star.chart2.DataSeries")
ydata = CreateUnoService("com.sun.star.chart2.data.LabeledDataSequence")
xdata = CreateUnoService("com.sun.star.chart2.data.LabeledDataSequence")
ydata.setValues(create_data_sequence(provider, y_repr, "values-y"))
if NOT IsMissing(label_repr) Then
ydata.setLabel(create_data_sequence(provider, label_repr, "label"))
end if
xdata.setValues(create_data_sequence(provider, x_repr, "values-x"))
series.setData(Array(ydata, xdata))
create_scatter_series = series
End Function
Function create_data_sequence(provider, repr, role)
seq = nothing
if provider.createDataSequenceByRangeRepresentationPossible(repr) Then
seq = provider.createDataSequenceByRangeRepresentation(repr)
seq.Role = role
end If
create_data_sequence = seq
End Function
' データの入れ替え
Function ExchangeData(data)
Dim a(0)
sn = UBound(data)
series = (UBound(data) + 1) * 2 -1
s1 = data(0)
n = UBound(s1(0))
Dim edata(n)
for i = 0 to n step 1
a = Array()
ReDim a(series)
for j = 0 to sn step 1
s = data(j)
x = s(0)
y = s(1)
a(j * 2) = x(i)
a(j * 2+1) = y(i)
next
edata(i) = a
next
ExchangeData = edata
End Function
}}
系列のデータの長さが違う場合を考慮していませんが、その場合には nan となるようにデータプロバイダから NotANumber プロパティを取得、空のデータ値として入れます。