スプレッドシート ドキュメントにグラフを挿入する
このトピックでは、Open XML SDK for Office のクラスを使用して、プログラムを使用してグラフをスプレッドシート ドキュメントに挿入する方法について説明します。
Row 要素
ここでは、行、セル、およびセル値の各要素を使用します。 したがって、これらの要素について理解していると役に立ちます。
ISO/IEC 29500 仕様の次のテキストでは、行 (<row/>
) 要素が導入されています。
行要素は、ワークシートの行全体についての情報を表し、ワークシート内の特定の行に対するすべてのセル定義を含みます。
次の row は、ワークシートの行 2 についての情報を表し、3 つのセル定義を含みます。
<row r="2" spans="2:12">
<c r="C2" s="1">
<f>PMT(B3/12,B4,-B5)</f>
<v>672.68336574300008</v>
</c>
<c r="D2">
<v>180</v>
</c>
<c r="E2">
<v>360</v>
</c>
</row>
© ISO/IEC 29500: 2016
次の XML スキーマ コード例では、行要素のコンテンツが定義されています。
<complexType name="CT_Row">
<sequence>
<element name="c" type="CT_Cell" minOccurs="0" maxOccurs="unbounded"/>
<element name="extLst" minOccurs="0" type="CT_ExtensionList"/>
</sequence>
<attribute name="r" type="xsd:unsignedInt" use="optional"/>
<attribute name="spans" type="ST_CellSpans" use="optional"/>
<attribute name="s" type="xsd:unsignedInt" use="optional" default="0"/>
<attribute name="customFormat" type="xsd:boolean" use="optional" default="false"/>
<attribute name="ht" type="xsd:double" use="optional"/>
<attribute name="hidden" type="xsd:boolean" use="optional" default="false"/>
<attribute name="customHeight" type="xsd:boolean" use="optional" default="false"/>
<attribute name="outlineLevel" type="xsd:unsignedByte" use="optional" default="0"/>
<attribute name="collapsed" type="xsd:boolean" use="optional" default="false"/>
<attribute name="thickTop" type="xsd:boolean" use="optional" default="false"/>
<attribute name="thickBot" type="xsd:boolean" use="optional" default="false"/>
<attribute name="ph" type="xsd:boolean" use="optional" default="false"/>
</complexType>
Cell 要素
ISO/IEC 29500 仕様の次のテキストでは、セル (<c/>
) 要素が導入されています。
このコレクションは、ワークシート内のセルを表します。 セルの場所 (参照)、値、データ型、書式設定、および式についての情報がここでは表されます。
次の例では、グリッド内のアドレスが C6、スタイル インデックスが 6、値メタデータ インデックスが 15 であるセルに対して格納される情報を示します。 セルには、式だけでなく、その式の計算結果も含まれます。
<c r="C6" s="1" vm="15">
<f>CUBEVALUE("xlextdat9 Adventure Works",C$5,$A6)</f>
<v>2838512.355</v>
</c>
© ISO/IEC 29500: 2016
次の XML スキーマ コード例では、この要素のコンテンツが定義されています。
<complexType name="CT_Cell">
<sequence>
<element name="f" type="CT_CellFormula" minOccurs="0" maxOccurs="1"/>
<element name="v" type="ST_Xstring" minOccurs="0" maxOccurs="1"/>
<element name="is" type="CT_Rst" minOccurs="0" maxOccurs="1"/>
<element name="extLst" minOccurs="0" type="CT_ExtensionList"/>
</sequence>
<attribute name="r" type="ST_CellRef" use="optional"/>
<attribute name="s" type="xsd:unsignedInt" use="optional" default="0"/>
<attribute name="t" type="ST_CellType" use="optional" default="n"/>
<attribute name="cm" type="xsd:unsignedInt" use="optional" default="0"/>
<attribute name="vm" type="xsd:unsignedInt" use="optional" default="0"/>
<attribute name="ph" type="xsd:boolean" use="optional" default="false"/>
</complexType>
セル値要素
ISO/IEC 29500 仕様の次のテキストでは、セル値 (<c/>
) 要素が導入されています。
この要素は、セルに含まれる値を表します。 セルに文字列が含まれる場合、この値は共有文字列テーブルのインデックスであり、実際の文字列値を指しています。 文字列以外の場合は、セルの値はこの要素で直接表されます。 式を含むセルは、この要素での式の最終的な計算結果を表します。
共有文字列テーブルを実装したくないアプリケーションの場合、"インライン文字列" は、共有文字列テーブルで表されるのと同じ方法で、
<c/>
の下の<is/>
要素 (<c/>
の下の<v/>
要素ではなく) で表される場合があります。© ISO/IEC 29500: 2016
次の例では、セル B4 には値 360 が含まれます。
<c r="B4">
<v>360</v>
</c>
サンプル コードのしくみ
スプレッドシート ファイルを読み取り/書き込みアクセス用に開いた後、指定したワークシートが存在するかどうかをコードで検証します。 次に、AddNewPart メソッドを使用して新しいDrawingsPart オブジェクトを追加し、ワークシートに追加し、ワークシート パーツを保存します。 次に、コードは新しいChartPart オブジェクトを追加し、ChartPart
オブジェクトに新しいChartSpace オブジェクトを追加し、グラフの言語が英語と米国のChartSpace
オブジェクトに新しいEditingLanguage オブジェクトを追加します。
IEnumerable<Sheet>? sheets = document.WorkbookPart?.Workbook.Descendants<Sheet>().Where(s => s.Name == worksheetName);
if (sheets is null || sheets.Count() == 0)
{
// The specified worksheet does not exist.
return;
}
string? id = sheets.First().Id;
if (id is null)
{
// The worksheet does not have an ID.
return;
}
WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart!.GetPartById(id);
// Add a new drawing to the worksheet.
DrawingsPart drawingsPart = worksheetPart.AddNewPart<DrawingsPart>();
worksheetPart.Worksheet.Append(new DocumentFormat.OpenXml.Spreadsheet.Drawing()
{ Id = worksheetPart.GetIdOfPart(drawingsPart) });
// Add a new chart and set the chart language to English-US.
ChartPart chartPart = drawingsPart.AddNewPart<ChartPart>();
chartPart.ChartSpace = new ChartSpace();
chartPart.ChartSpace.Append(new EditingLanguage() { Val = new StringValue("en-US") });
DocumentFormat.OpenXml.Drawing.Charts.Chart chart = chartPart.ChartSpace.AppendChild<DocumentFormat.OpenXml.Drawing.Charts.Chart>(
new DocumentFormat.OpenXml.Drawing.Charts.Chart());
このコードでは、BarDirectionValues オブジェクトを Column
に設定し、オブジェクトを Clustered
に設定BarGroupingValues新しいBarChart オブジェクトを作成することで、新しいクラスター化縦棒グラフを作成します。
次に、コードは、 Dictionary
クラスの各キーを反復処理します。 キーごとに、BarChartSeries オブジェクトを BarChart
オブジェクトに追加し、BarChartSeries
オブジェクトのSeriesText オブジェクトをキーと等しく設定します。 キーごとに、BarChartSeries
オブジェクトのValues
コレクションにNumberLiteral オブジェクトを追加し、NumberLiteral
オブジェクトをキーに対応するDictionary
クラス値と等しく設定します。
// Create a new clustered column chart.
PlotArea plotArea = chart.AppendChild<PlotArea>(new PlotArea());
Layout layout = plotArea.AppendChild<Layout>(new Layout());
BarChart barChart = plotArea.AppendChild<BarChart>(new BarChart(new BarDirection()
{ Val = new EnumValue<BarDirectionValues>(BarDirectionValues.Column) },
new BarGrouping() { Val = new EnumValue<BarGroupingValues>(BarGroupingValues.Clustered) }));
uint i = 0;
// Iterate through each key in the Dictionary collection and add the key to the chart Series
// and add the corresponding value to the chart Values.
foreach (string key in data.Keys)
{
BarChartSeries barChartSeries = barChart.AppendChild<BarChartSeries>(new BarChartSeries(new Index()
{
Val = new UInt32Value(i)
},
new Order() { Val = new UInt32Value(i) },
new SeriesText(new NumericValue() { Text = key })));
StringLiteral strLit = barChartSeries.AppendChild<CategoryAxisData>(new CategoryAxisData()).AppendChild<StringLiteral>(new StringLiteral());
strLit.Append(new PointCount() { Val = new UInt32Value(1U) });
strLit.AppendChild<StringPoint>(new StringPoint() { Index = new UInt32Value(0U) }).Append(new NumericValue(title));
NumberLiteral numLit = barChartSeries.AppendChild<DocumentFormat.OpenXml.Drawing.Charts.Values>(
new DocumentFormat.OpenXml.Drawing.Charts.Values()).AppendChild<NumberLiteral>(new NumberLiteral());
numLit.Append(new FormatCode("General"));
numLit.Append(new PointCount() { Val = new UInt32Value(1U) });
numLit.AppendChild<NumericPoint>(new NumericPoint() { Index = new UInt32Value(0u) }).Append
(new NumericValue(data[key].ToString()));
i++;
}
コードは、 CategoryAxis オブジェクトと ValueAxis オブジェクトをグラフに追加し、 Scaling、 AxisPosition、 TickLabelPosition、 CrossingAxis、 Crosses、 AutoLabeled、 LabelAlignment、 LabelOffsetの各プロパティの値を設定します。 また、 Legend オブジェクトをグラフに追加し、グラフ パーツを保存します。
barChart.Append(new AxisId() { Val = new UInt32Value(48650112u) });
barChart.Append(new AxisId() { Val = new UInt32Value(48672768u) });
// Add the Category Axis.
CategoryAxis catAx = plotArea.AppendChild<CategoryAxis>(new CategoryAxis(new AxisId()
{ Val = new UInt32Value(48650112u) }, new Scaling(new Orientation()
{
Val = new EnumValue<DocumentFormat.OpenXml.Drawing.Charts.OrientationValues>(DocumentFormat.OpenXml.Drawing.Charts.OrientationValues.MinMax)
}),
new AxisPosition() { Val = new EnumValue<AxisPositionValues>(AxisPositionValues.Bottom) },
new TickLabelPosition() { Val = new EnumValue<TickLabelPositionValues>(TickLabelPositionValues.NextTo) },
new CrossingAxis() { Val = new UInt32Value(48672768U) },
new Crosses() { Val = new EnumValue<CrossesValues>(CrossesValues.AutoZero) },
new AutoLabeled() { Val = new BooleanValue(true) },
new LabelAlignment() { Val = new EnumValue<LabelAlignmentValues>(LabelAlignmentValues.Center) },
new LabelOffset() { Val = new UInt16Value((ushort)100) }));
// Add the Value Axis.
ValueAxis valAx = plotArea.AppendChild<ValueAxis>(new ValueAxis(new AxisId() { Val = new UInt32Value(48672768u) },
new Scaling(new Orientation()
{
Val = new EnumValue<DocumentFormat.OpenXml.Drawing.Charts.OrientationValues>(
DocumentFormat.OpenXml.Drawing.Charts.OrientationValues.MinMax)
}),
new AxisPosition() { Val = new EnumValue<AxisPositionValues>(AxisPositionValues.Left) },
new MajorGridlines(),
new DocumentFormat.OpenXml.Drawing.Charts.NumberingFormat()
{
FormatCode = new StringValue("General"),
SourceLinked = new BooleanValue(true)
}, new TickLabelPosition()
{
Val = new EnumValue<TickLabelPositionValues>
(TickLabelPositionValues.NextTo)
}, new CrossingAxis() { Val = new UInt32Value(48650112U) },
new Crosses() { Val = new EnumValue<CrossesValues>(CrossesValues.AutoZero) },
new CrossBetween() { Val = new EnumValue<CrossBetweenValues>(CrossBetweenValues.Between) }));
// Add the chart Legend.
Legend legend = chart.AppendChild<Legend>(new Legend(new LegendPosition() { Val = new EnumValue<LegendPositionValues>(LegendPositionValues.Right) },
new Layout()));
chart.Append(new PlotVisibleOnly() { Val = new BooleanValue(true) });
コードは、 WorksheetDrawing オブジェクトを作成し、 TwoCellAnchor
オブジェクトを追加することで、ワークシート上にグラフを配置します。
TwoCellAnchor
オブジェクトは、FromMarkerとToMarkerアンカーの間で行と列を移動する場合にグラフを移動またはサイズ変更する方法を指定します。 次に、グラフを格納する GraphicFrame オブジェクトを作成し、グラフに "Chart 1" という名前を付けます。
// Position the chart on the worksheet using a TwoCellAnchor object.
drawingsPart.WorksheetDrawing = new WorksheetDrawing();
TwoCellAnchor twoCellAnchor = drawingsPart.WorksheetDrawing.AppendChild<TwoCellAnchor>(new TwoCellAnchor());
twoCellAnchor.Append(new DocumentFormat.OpenXml.Drawing.Spreadsheet.FromMarker(new ColumnId("9"),
new ColumnOffset("581025"),
new RowId("17"),
new RowOffset("114300")));
twoCellAnchor.Append(new DocumentFormat.OpenXml.Drawing.Spreadsheet.ToMarker(new ColumnId("17"),
new ColumnOffset("276225"),
new RowId("32"),
new RowOffset("0")));
// Append a GraphicFrame to the TwoCellAnchor object.
DocumentFormat.OpenXml.Drawing.Spreadsheet.GraphicFrame graphicFrame =
twoCellAnchor.AppendChild<DocumentFormat.OpenXml.
Drawing.Spreadsheet.GraphicFrame>(new DocumentFormat.OpenXml.Drawing.
Spreadsheet.GraphicFrame());
graphicFrame.Macro = "";
graphicFrame.Append(new DocumentFormat.OpenXml.Drawing.Spreadsheet.NonVisualGraphicFrameProperties(
new DocumentFormat.OpenXml.Drawing.Spreadsheet.NonVisualDrawingProperties() { Id = new UInt32Value(2u), Name = "Chart 1" },
new DocumentFormat.OpenXml.Drawing.Spreadsheet.NonVisualGraphicFrameDrawingProperties()));
graphicFrame.Append(new Transform(new Offset() { X = 0L, Y = 0L },
new Extents() { Cx = 0L, Cy = 0L }));
graphicFrame.Append(new Graphic(new GraphicData(new ChartReference() { Id = drawingsPart.GetIdOfPart(chartPart) })
{ Uri = "http://schemas.openxmlformats.org/drawingml/2006/chart" }));
twoCellAnchor.Append(new ClientData());
サンプル コード
注:
[!メモ] このコードを実行できるのは 1 回だけです。 グラフの複数のインスタンスを作成することはできません。
以下に、C# と Visual Basic による完全なサンプル コードを示します。
static void InsertChartInSpreadsheet(string docName, string worksheetName, string title, Dictionary<string, int> data)
{
// Open the document for editing.
using (SpreadsheetDocument document = SpreadsheetDocument.Open(docName, true))
{
IEnumerable<Sheet>? sheets = document.WorkbookPart?.Workbook.Descendants<Sheet>().Where(s => s.Name == worksheetName);
if (sheets is null || sheets.Count() == 0)
{
// The specified worksheet does not exist.
return;
}
string? id = sheets.First().Id;
if (id is null)
{
// The worksheet does not have an ID.
return;
}
WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart!.GetPartById(id);
// Add a new drawing to the worksheet.
DrawingsPart drawingsPart = worksheetPart.AddNewPart<DrawingsPart>();
worksheetPart.Worksheet.Append(new DocumentFormat.OpenXml.Spreadsheet.Drawing()
{ Id = worksheetPart.GetIdOfPart(drawingsPart) });
// Add a new chart and set the chart language to English-US.
ChartPart chartPart = drawingsPart.AddNewPart<ChartPart>();
chartPart.ChartSpace = new ChartSpace();
chartPart.ChartSpace.Append(new EditingLanguage() { Val = new StringValue("en-US") });
DocumentFormat.OpenXml.Drawing.Charts.Chart chart = chartPart.ChartSpace.AppendChild<DocumentFormat.OpenXml.Drawing.Charts.Chart>(
new DocumentFormat.OpenXml.Drawing.Charts.Chart());
// Create a new clustered column chart.
PlotArea plotArea = chart.AppendChild<PlotArea>(new PlotArea());
Layout layout = plotArea.AppendChild<Layout>(new Layout());
BarChart barChart = plotArea.AppendChild<BarChart>(new BarChart(new BarDirection()
{ Val = new EnumValue<BarDirectionValues>(BarDirectionValues.Column) },
new BarGrouping() { Val = new EnumValue<BarGroupingValues>(BarGroupingValues.Clustered) }));
uint i = 0;
// Iterate through each key in the Dictionary collection and add the key to the chart Series
// and add the corresponding value to the chart Values.
foreach (string key in data.Keys)
{
BarChartSeries barChartSeries = barChart.AppendChild<BarChartSeries>(new BarChartSeries(new Index()
{
Val = new UInt32Value(i)
},
new Order() { Val = new UInt32Value(i) },
new SeriesText(new NumericValue() { Text = key })));
StringLiteral strLit = barChartSeries.AppendChild<CategoryAxisData>(new CategoryAxisData()).AppendChild<StringLiteral>(new StringLiteral());
strLit.Append(new PointCount() { Val = new UInt32Value(1U) });
strLit.AppendChild<StringPoint>(new StringPoint() { Index = new UInt32Value(0U) }).Append(new NumericValue(title));
NumberLiteral numLit = barChartSeries.AppendChild<DocumentFormat.OpenXml.Drawing.Charts.Values>(
new DocumentFormat.OpenXml.Drawing.Charts.Values()).AppendChild<NumberLiteral>(new NumberLiteral());
numLit.Append(new FormatCode("General"));
numLit.Append(new PointCount() { Val = new UInt32Value(1U) });
numLit.AppendChild<NumericPoint>(new NumericPoint() { Index = new UInt32Value(0u) }).Append
(new NumericValue(data[key].ToString()));
i++;
}
barChart.Append(new AxisId() { Val = new UInt32Value(48650112u) });
barChart.Append(new AxisId() { Val = new UInt32Value(48672768u) });
// Add the Category Axis.
CategoryAxis catAx = plotArea.AppendChild<CategoryAxis>(new CategoryAxis(new AxisId()
{ Val = new UInt32Value(48650112u) }, new Scaling(new Orientation()
{
Val = new EnumValue<DocumentFormat.OpenXml.Drawing.Charts.OrientationValues>(DocumentFormat.OpenXml.Drawing.Charts.OrientationValues.MinMax)
}),
new AxisPosition() { Val = new EnumValue<AxisPositionValues>(AxisPositionValues.Bottom) },
new TickLabelPosition() { Val = new EnumValue<TickLabelPositionValues>(TickLabelPositionValues.NextTo) },
new CrossingAxis() { Val = new UInt32Value(48672768U) },
new Crosses() { Val = new EnumValue<CrossesValues>(CrossesValues.AutoZero) },
new AutoLabeled() { Val = new BooleanValue(true) },
new LabelAlignment() { Val = new EnumValue<LabelAlignmentValues>(LabelAlignmentValues.Center) },
new LabelOffset() { Val = new UInt16Value((ushort)100) }));
// Add the Value Axis.
ValueAxis valAx = plotArea.AppendChild<ValueAxis>(new ValueAxis(new AxisId() { Val = new UInt32Value(48672768u) },
new Scaling(new Orientation()
{
Val = new EnumValue<DocumentFormat.OpenXml.Drawing.Charts.OrientationValues>(
DocumentFormat.OpenXml.Drawing.Charts.OrientationValues.MinMax)
}),
new AxisPosition() { Val = new EnumValue<AxisPositionValues>(AxisPositionValues.Left) },
new MajorGridlines(),
new DocumentFormat.OpenXml.Drawing.Charts.NumberingFormat()
{
FormatCode = new StringValue("General"),
SourceLinked = new BooleanValue(true)
}, new TickLabelPosition()
{
Val = new EnumValue<TickLabelPositionValues>
(TickLabelPositionValues.NextTo)
}, new CrossingAxis() { Val = new UInt32Value(48650112U) },
new Crosses() { Val = new EnumValue<CrossesValues>(CrossesValues.AutoZero) },
new CrossBetween() { Val = new EnumValue<CrossBetweenValues>(CrossBetweenValues.Between) }));
// Add the chart Legend.
Legend legend = chart.AppendChild<Legend>(new Legend(new LegendPosition() { Val = new EnumValue<LegendPositionValues>(LegendPositionValues.Right) },
new Layout()));
chart.Append(new PlotVisibleOnly() { Val = new BooleanValue(true) });
// Position the chart on the worksheet using a TwoCellAnchor object.
drawingsPart.WorksheetDrawing = new WorksheetDrawing();
TwoCellAnchor twoCellAnchor = drawingsPart.WorksheetDrawing.AppendChild<TwoCellAnchor>(new TwoCellAnchor());
twoCellAnchor.Append(new DocumentFormat.OpenXml.Drawing.Spreadsheet.FromMarker(new ColumnId("9"),
new ColumnOffset("581025"),
new RowId("17"),
new RowOffset("114300")));
twoCellAnchor.Append(new DocumentFormat.OpenXml.Drawing.Spreadsheet.ToMarker(new ColumnId("17"),
new ColumnOffset("276225"),
new RowId("32"),
new RowOffset("0")));
// Append a GraphicFrame to the TwoCellAnchor object.
DocumentFormat.OpenXml.Drawing.Spreadsheet.GraphicFrame graphicFrame =
twoCellAnchor.AppendChild<DocumentFormat.OpenXml.
Drawing.Spreadsheet.GraphicFrame>(new DocumentFormat.OpenXml.Drawing.
Spreadsheet.GraphicFrame());
graphicFrame.Macro = "";
graphicFrame.Append(new DocumentFormat.OpenXml.Drawing.Spreadsheet.NonVisualGraphicFrameProperties(
new DocumentFormat.OpenXml.Drawing.Spreadsheet.NonVisualDrawingProperties() { Id = new UInt32Value(2u), Name = "Chart 1" },
new DocumentFormat.OpenXml.Drawing.Spreadsheet.NonVisualGraphicFrameDrawingProperties()));
graphicFrame.Append(new Transform(new Offset() { X = 0L, Y = 0L },
new Extents() { Cx = 0L, Cy = 0L }));
graphicFrame.Append(new Graphic(new GraphicData(new ChartReference() { Id = drawingsPart.GetIdOfPart(chartPart) })
{ Uri = "http://schemas.openxmlformats.org/drawingml/2006/chart" }));
twoCellAnchor.Append(new ClientData());
}
}