Accessing 3DPie Chart using Interop in c# - visual-c#-express-2010

/* Im creating a 3D Pie Chart using the code below. It works fine. The program export the Excel File. What i want to happen now is to disable the Category Name and Value Data Labels. And i want to change the Separator to New Line. How would i do it? Can someone help me with this? Please. Your help will be so much appreciated. Please refer from my codes below. */
private void btnGenerateChart_Click(object sender, EventArgs e){
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
object misValue = System.Reflection.Missing.Value;
int x = 2;
xlApp = new Excel.Application();
xlWorkBook = xlApp.Workbooks.Add(misValue);
// Create and select 1st sheet
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
try{
SqlCommand compass = _SqlConnection._SqlCon.CreateCommand();
compass.CommandText = ''sp_SelectRawData'';
compass.CommandType = CommandType.StoredProcedure;
_SqlConnection._SqlCon.Open();
SqlDataReader dreader = compass.ExecuteReader();
xlWorkSheet.Cells[1, 2] = ''Tag I - IV'';
xlWorkSheet.Cells[1, 3] = ''Tag V'';
xlWorkSheet.Cells[1, 4] = ''No Tag'';
while(dreader.Read()){
xlWorkSheet.Cells[x, 1] = dreader.ToString();
xlWorkSheet.Cells[x, 2] = dreader.ToString();
xlWorkSheet.Cells[x, 3] = dreader.ToString();
xlWorkSheet.Cells[x, 4] = dreader.ToString();
x++;
}
dreader.Close();
_SqlConnection._SqlCon.Close();
}
catch(Exception ex){
MessageBox.Show(ex.Message);
}
// Chart range is used to select cells
Excel.Range chartRange;
chartRange = xlWorkSheet.get_Range(''A1'', ''D'' + (x - 1));
chartRange.Columns.EntireColumn.AutoFit();
chartRange = xlWorkSheet.get_Range(''B2'', ''D'' + (x - 1));
chartRange.Columns.NumberFormat = ''_(#,##0.00_);_((#,##0.00);_(\''-\''??_);_(#_)'';
// Create and select 2nd sheet
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(2);
Excel.ChartObjects xlCharts = (Excel.ChartObjects)xlWorkSheet.ChartObjects(Type.Missing);
// Chart size
Excel.ChartObject myChart = (Excel.ChartObject)xlCharts.Add(10, 10, 750, 350);
Excel.Chart chartPage = myChart.Chart;
chartPage.HasLegend = true;
chartPage.ChartTitle.Text = ''Final IAS Provition'';
var xAxis = (Excel.Axis)chartPage.Axes(Excel.XlAxisType.xlValue, Excel.XlAxisGroup.xlPrimary);
xAxis.HasTitle = true;
xAxis.AxisTitle.Text = ''Scale Value'';
var yAxis = (Excel.Axis)chartPage.Axes(Excel.XlAxisType.xlCategory, Excel.XlAxisGroup.xlPrimary);
yAxis.HasTitle = true;
yAxis.AxisTitle.Text = ''Originating Unit'';
// Refer chart data source from the1st sheet
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
chartRange = xlWorkSheet.get_Range(''A1'', ''D'' + (x - 1));
// Go to sheet two
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(2);
// Set chart data source
chartPage.SetSourceData(chartRange, misValue);
chartPage.ApplyDataLabels();
chartPage.ChartType = Excel.XlChartType.xl3DPie;
chartPage.Rotation = 0;
chartPage.Perspective = Convert.ToInt16(0.1);
xlWorkBook.CheckCompatibility = false;
chartRange.Worksheet.Protect(Password: ''987654321'', AllowFormattingColumns: true, AllowFiltering: true);
xlWorkBook.SaveAs(yourpath + ''.xls'', Excel.XlFileFormat.xlWorkbookNormal, ''123'', misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue);
xlWorkBook.Close(true, misValue, misValue);
xlApp.Quit();
releaseObject(xlWorkSheet);
releaseObject(xlWorkBook);
releaseObject(xlApp);
}
private void releaseObject(object obj){
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
obj = null;
}
catch(Exception ex){
obj = null;
}
finally{
GC.Collect();
}
}

Related

how to update ext list value of pptx scatter chart

Read pptx template then use new data to replace it, there is a scatter chart
associated excel data
xVal and yVal could replace successfully but how to replace C column (extList) ?
xVal and yVal replace by below manner
final CTScatterSer ser = serList.get(0);
final CTAxDataSource xVal = ser.getXVal();
final CTNumDataSource yVal = ser.getYVal();
final CTExtension ctExtension = ser.getExtLst().getExtList().get(0);
final long ptCount = xVal.getNumRef().getNumCache().getPtCount().getVal();
for (int i = 0; i < scData.size(); i++) {
SCNameDouble data = scData.get(i);
CTNumVal xNumVal = ptCount > i ? xVal.getNumRef().getNumCache().getPtArray(i)
: xVal.getNumRef().getNumCache().addNewPt();
xNumVal.setIdx(i);
xNumVal.setV(String.format("%.2f", data.xValue));
CTNumVal yNumVal = ptCount > i ? yVal.getNumRef().getNumCache().getPtArray(i)
: yVal.getNumRef().getNumCache().addNewPt();
yNumVal.setIdx(i);
yNumVal.setV(String.format("%.2f", data.yValue));
}
final int newSize = scData.size();
xVal.getNumRef().setF(
replaceRowEnd(xVal.getNumRef().getF(),
ptCount,
newSize));
yVal.getNumRef().setF(
replaceRowEnd(yVal.getNumRef().getF(),
ptCount,
newSize));
xVal.getNumRef().getNumCache().getPtCount().setVal(newSize);
yVal.getNumRef().getNumCache().getPtCount().setVal(newSize);
Using current apache poi versions one should not trying manipulating charts using the low level CT... classes. There is XDDF for such cases now.
If it comes to PowerPoint charts, then the need is always updating the data in the embedded workbook and updating the data in the chart. See Java edit bar chart in ppt by using poi for an example using bar chart.
Of course a scatter chart is another case then as it not has a category axis but has two value axes. But this also can be updated using XDDF.
The biggest problem you have is the data labels. There is not full support for chart data labels in XDDF upto now. And since you are talkig about extLst and your Excel table shows the data labels in a cell range, I suspect you have set the data labels comming from a cell range. This is a new feature which was not present when Microsoft had published Office Open XML. So not even the low level CT... classes are able to support that feature.
The only way is to manipulate the XML using pure XML manupulating based on org.apache.xmlbeans.XmlObject.
The following shows this on sample of a template you seems to use according to your question.
ScatterChartSample.pptx:
Code:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.xslf.usermodel.*;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.AreaReference;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumns;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn;
public class PowerPointChangeScatterChartData {
//patched version of XSSFTable.updateHeaders, see https://stackoverflow.com/questions/55532006/renaming-headers-of-xssftable-with-apache-poi-leads-to-corrupt-xlsx-file/55539181#55539181
static void updateHeaders(XSSFTable table) {
XSSFSheet sheet = (XSSFSheet)table.getParent();
CellReference ref = table.getStartCellReference();
if (ref == null) return;
int headerRow = ref.getRow();
int firstHeaderColumn = ref.getCol();
XSSFRow row = sheet.getRow(headerRow);
DataFormatter formatter = new DataFormatter();
if (row != null /*&& row.getCTRow().validate()*/) {
int cellnum = firstHeaderColumn;
CTTableColumns ctTableColumns = table.getCTTable().getTableColumns();
if(ctTableColumns != null) {
for (CTTableColumn col : ctTableColumns.getTableColumnList()) {
XSSFCell cell = row.getCell(cellnum);
if (cell != null) {
col.setName(formatter.formatCellValue(cell));
}
cellnum++;
}
}
}
}
static void updateScatterChart(XSLFChart chart, Object[][] data) throws Exception {
// get chart's data source which is a Excel sheet
XSSFWorkbook chartDataWorkbook = chart.getWorkbook();
String sheetName = chartDataWorkbook.getSheetName(0);
XSSFSheet chartDataSheet = chartDataWorkbook.getSheet(sheetName);
// current Office uses a table as data source
// so get that table if present
XSSFTable chartDataTable = null;
if (chartDataSheet.getTables().size() > 0) {
chartDataTable = chartDataSheet.getTables().get(0);
}
if (chart.getChartSeries().size() == 1) { // we will process only one chart data
XDDFChartData chartData = chart.getChartSeries().get(0);
if (chartData.getSeriesCount() == 1) { // we will process only templates having one series
int rMin = 1; // first row (0) is headers row
int rMax = data.length - 1;
// column 0 is X-Values
int c = 0;
// set new x data
XDDFDataSource xs = null;
for (int r = rMin; r <= rMax; r++) {
XSSFRow row = chartDataSheet.getRow(r); if (row == null) row = chartDataSheet.createRow(r);
XSSFCell cell = row.getCell(c); if (cell == null) cell = row.createCell(c);
cell.setCellValue((Double)data[r][c]); // in sheet
}
xs = XDDFDataSourcesFactory.fromNumericCellRange(chartDataSheet, new CellRangeAddress(rMin,rMax,c,c)); // in chart
// set new x-title in sheet
String xTitle = (String)data[0][c];
chartDataSheet.getRow(0).getCell(c).setCellValue(xTitle); // in sheet
// column 1 is Y-Values
c = 1;
// set new y data in sheet and in chart
XDDFNumericalDataSource<Double> ys = null;
for (int r = rMin; r <= rMax; r++) {
XSSFRow row = chartDataSheet.getRow(r); if (row == null) row = chartDataSheet.createRow(r);
XSSFCell cell = row.getCell(c); if (cell == null) cell = row.createCell(c);
cell.setCellValue((Double)data[r][c]); // in sheet
}
ys = XDDFDataSourcesFactory.fromNumericCellRange(chartDataSheet, new CellRangeAddress(rMin,rMax,c,c));
XDDFChartData.Series series1 = chartData.getSeries(0);
series1.replaceData(xs, ys); // in chart
// set new y-title in sheet and in chart
String yTitle = (String)data[0][c];
chartDataSheet.getRow(0).getCell(c).setCellValue(yTitle); // in sheet
series1.setTitle(yTitle, new CellReference(sheetName, 0, c, true, true)); // in chart
series1.plot();
// column 2 is data-labels-range
c = 2;
// set new data labels data in sheet and in chart
XDDFDataSource dataLabelsRangeSource = null;
for (int r = rMin; r <= rMax; r++) {
XSSFRow row = chartDataSheet.getRow(r); if (row == null) row = chartDataSheet.createRow(r);
XSSFCell cell = row.getCell(c); if (cell == null) cell = row.createCell(c);
cell.setCellValue((String)data[r][c]); // in sheet
}
dataLabelsRangeSource = XDDFDataSourcesFactory.fromStringCellRange(chartDataSheet, new CellRangeAddress(rMin,rMax,c,c)); // in chart
updateDataLabelsRange(chart, dataLabelsRangeSource); // in chart
// set new data-labels-title in sheet
String descrTitle = (String)data[0][c];
chartDataSheet.getRow(0).getCell(c).setCellValue(descrTitle); // in sheet
// update the table if present
if (chartDataTable != null) {
CellReference topLeft = new CellReference(chartDataSheet.getRow(0).getCell(0));
CellReference bottomRight = new CellReference(chartDataSheet.getRow(rMax).getCell(c));
AreaReference tableArea = chartDataWorkbook.getCreationHelper().createAreaReference(topLeft, bottomRight);
chartDataTable.setArea(tableArea);
updateHeaders(chartDataTable);
}
}
}
}
static void updateDataLabelsRange(XDDFChart chart, XDDFDataSource dataLabelsRangeSource) {
String declareNameSpaces = "declare namespace c='http://schemas.openxmlformats.org/drawingml/2006/chart'; "
+ "declare namespace c15='http://schemas.microsoft.com/office/drawing/2012/chart' ";
org.apache.xmlbeans.XmlObject[] selectedObjects = chart.getCTChart().selectPath(
declareNameSpaces
+ ".//c:ext[c15:datalabelsRange]"); // needs net.sf.saxon - Saxon-HE (Saxon-HE-10.6.jar)
if (selectedObjects.length > 0) { // we have at least one ext containing datalabelsRange
org.apache.xmlbeans.XmlObject ext = selectedObjects[0]; // get first ext containing datalabelsRange
// get dataLabelsRange
org.apache.xmlbeans.XmlObject[] datalabelsRanges = ext.selectChildren(new javax.xml.namespace.QName("http://schemas.microsoft.com/office/drawing/2012/chart", "datalabelsRange", "c15"));
org.apache.xmlbeans.XmlObject dataLabelsRange = datalabelsRanges[0];
// set formula
org.apache.xmlbeans.XmlObject[] formulas = dataLabelsRange.selectChildren(new javax.xml.namespace.QName("http://schemas.microsoft.com/office/drawing/2012/chart", "f", "c15"));
org.apache.xmlbeans.XmlObject formula = formulas[0];
((org.apache.xmlbeans.impl.values.XmlObjectBase)formula).setStringValue(dataLabelsRangeSource.getFormula());
// get dlblRangeCache
org.apache.xmlbeans.XmlObject[] dlblRangeCaches = dataLabelsRange.selectChildren(new javax.xml.namespace.QName("http://schemas.microsoft.com/office/drawing/2012/chart", "dlblRangeCache", "c15"));
org.apache.xmlbeans.XmlObject dlblRangeCache = dlblRangeCaches[0];
// empty the cache
dlblRangeCache.newCursor().removeXmlContents();
// create new cache from dataLabelsRangeSource
org.openxmlformats.schemas.drawingml.x2006.chart.CTStrData cache = org.openxmlformats.schemas.drawingml.x2006.chart.CTStrData.Factory.newInstance();
dataLabelsRangeSource.fillStringCache(cache);
// set new cache
dlblRangeCache.set(cache);
}
}
public static void main(String[] args) throws Exception {
String filePath = "ScatterChartSample.pptx"; // has template scatter chart
String filePathNew = "ScatterChartSample_New.pptx";
Object[][] data = new Object[][] { // new data 1 series, 6 x-y-values and data labels
{"X-Values", "Y-Values", "DataLabels"}, // series title
{0.7d, 1.7d, "aa"}, // x1
{1.8d, 3.2d, "bb"}, // x2
{2.6d, 2.8d, "cc"}, // x3
{1.7d, 3.7d, "dd"}, // x4
{2.8d, 4.2d, "ee"}, // x5
{3.6d, 1.8d, "ff"} // x6
};
XMLSlideShow slideShow = new XMLSlideShow(new FileInputStream(filePath));
XSLFChart chart = slideShow.getCharts().get(0);
updateScatterChart(chart, data);
FileOutputStream out = new FileOutputStream(filePathNew);
slideShow.write(out);
out.close();
slideShow.close();
}
}
Resulting ScatterChartSample_New.pptx:
Note: Tested and works using current apache poi 5.2.0.
To be able to use XPath as .//c:ext[c15:datalabelsRange] it needs net.sf.saxon - Saxon-HE (Saxon-HE-10.6.jar in my case).
And it needs poi-ooxml-full-5.2.0.jar and not only the lite version of ooxml-schemas.

export generated excel variable to real excel file

this is how I generated Excel variable:
Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook excelworkBook;
Microsoft.Office.Interop.Excel.Worksheet excelSheet;
Microsoft.Office.Interop.Excel.Range excelCellrange;
excelworkBook = excel.Application.Workbooks.Add(Type.Missing);
excelSheet = (Microsoft.Office.Interop.Excel.Worksheet)excelworkBook.ActiveSheet;
//proper data from xml data field to store in excel
// ************************
//generate a data table and fill excell cell
excelCellrange = excelSheet.Range[excelSheet.Cells[1, 1],
excelSheet.Cells[theDataSet.Tables[0].Rows.Count+1, theDataSet.Tables[0].Columns.Count]];
excelCellrange.Font.ThemeColor =
Microsoft.Office.Interop.Excel.XlThemeColor.xlThemeColorAccent1;
excelCellrange.EntireColumn.AutoFit();
Microsoft.Office.Interop.Excel.Borders border = excelCellrange.Borders;
border.LineStyle = Microsoft.Office.Interop.Excel.XlLineStyle.xlContinuous;
border.Weight = 3d;
excel.Columns.AutoFit();
excel.DisplayAlerts = false;
excel.Visible = true;
now the question is how save this excel variable to real excel file to specific destination ?
best regards.
this is how I figure out this problem that maybe help someone else:
Microsoft.Office.Interop.Excel.Application excel = new
Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook excelworkBook;
Microsoft.Office.Interop.Excel.Worksheet excelSheet;
Microsoft.Office.Interop.Excel.Range excelCellrange;
excelworkBook = excel.Application.Workbooks.Add(Type.Missing);
excelSheet = (Microsoft.Office.Interop.Excel.Worksheet)excelworkBook.ActiveSheet;
XmlDocument xml = new XmlDocument();
xml.LoadXml(dtAll.Rows[gridEX1.CurrentRow.RowIndex]["Data"].ToString());
StringReader theReader = new StringReader(xml.InnerXml);
DataSet theDataSet = new DataSet();
theDataSet.ReadXml(theReader);
excel.Caption = dtAll.Rows[gridEX1.CurrentRow.RowIndex]["docID"].ToString() + "_" + dtAll.Rows[gridEX1.CurrentRow.RowIndex]["DocTitle"].ToString() + "_" + dtAll.Rows[gridEX1.CurrentRow.RowIndex]["DocDetails"].ToString();
excel.StandardFont = "B Nazanin";
excel.StatusBar = "col count: " + theDataSet.Tables[0].Rows.Count;
for (int i = 0; i < theDataSet.Tables[0].Columns.Count; i++)
{
excel.Cells[1, i + 1] = theDataSet.Tables[0].Columns[i].ColumnName;
excel.Cells[1, i + 1].Font.Color = System.Drawing.Color.Blue;
for (int j = 0; j < theDataSet.Tables[0].Rows.Count; j++)
{
excel.Cells[j + 2, i + 1].Font.Color = System.Drawing.Color.Black;
excel.Cells[j + 2, i + 1] = theDataSet.Tables[0].Rows[j][i].ToString();
}
}
excelCellrange = excelSheet.Range[excelSheet.Cells[1, 1], excelSheet.Cells[theDataSet.Tables[0].Rows.Count + 1, theDataSet.Tables[0].Columns.Count]];
excelCellrange.Font.ThemeColor = Microsoft.Office.Interop.Excel.XlThemeColor.xlThemeColorAccent1;
excelCellrange.EntireColumn.AutoFit();
Microsoft.Office.Interop.Excel.Borders border = excelCellrange.Borders;
border.LineStyle = Microsoft.Office.Interop.Excel.XlLineStyle.xlContinuous;
border.Weight = 3d;
byte[] output = Encoding.UTF8.GetBytes(xml.InnerXml);
string strfn = GroupTitle + ".xlsx";
if (File.Exists(strfn))
{
File.Delete(strfn);
}
FileStream fs = new FileStream(strfn, FileMode.CreateNew, FileAccess.Write);
fs.Write(output, 0, output.Length);
fs.Flush();
fs.Close();
string dest = Global.DocOutputPath.Substring(0, Global.DocOutputPath.Length - 1) + GroupTitle + ".xlsx";
if (File.Exists(dest))
{
DialogResult dialogResult = MessageBox.Show("are you sure about rewrite on file?", "warnning", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
File.Copy(strfn, dest);
File.Delete(dest);
}
else if (dialogResult == DialogResult.No)
{
return;
}
}
else
{
File.Copy(strfn, dest);
}

Add and view dataLabels (CTDLbls) in lineChart excel graph

I've developed the following code, but is not fully acomplishing what I need.
I would like to have the chance to set some specific datalabels of this serie
public static void main(String[] args) {
Workbook wb = new XSSFWorkbook();
Sheet dataSheet = wb.createSheet("linechart");
final int NUM_OF_ROWS = 10;
final int NUM_OF_COLUMNS = 4;
Row row;
Cell cell;
for (int rowIndex = 0; rowIndex < NUM_OF_ROWS; rowIndex++) {
row = dataSheet.createRow((short) rowIndex);
for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
if (colIndex<3) {
cell = row.createCell((short) colIndex);
cell.setCellValue(rowIndex * ((colIndex + 1) + ((int) (Math.random() * 10))));
}
else{
if (rowIndex == 0){
cell = row.createCell((short) colIndex);
cell.setCellValue("This is the first comment");
}
else if (rowIndex == 3){
cell = row.createCell((short) colIndex);
cell.setCellValue("This is another comment");
}
}
}
}
Drawing drawing = dataSheet.createDrawingPatriarch();
ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, NUM_OF_COLUMNS + 2, 3, NUM_OF_COLUMNS + 15, 20);
//XSSFChart xlsxChart = XSSFChart.createChart();
Chart chart = drawing.createChart(anchor);
ChartLegend legend = chart.getOrCreateLegend();
legend.setPosition(LegendPosition.RIGHT);
LineChartData data = chart.getChartDataFactory().createLineChartData();
ChartAxis bottomAxis = chart.getChartAxisFactory().createCategoryAxis(AxisPosition.BOTTOM);
ValueAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT);
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
ChartDataSource<Number> xs = DataSources.fromNumericCellRange(dataSheet, new CellRangeAddress(0, NUM_OF_ROWS - 1, 0, 0));
ChartDataSource<Number> ys1 = DataSources.fromNumericCellRange(dataSheet, new CellRangeAddress(0, NUM_OF_ROWS - 1, 1, 1));
ChartDataSource<Number> ys2 = DataSources.fromNumericCellRange(dataSheet, new CellRangeAddress(0, NUM_OF_ROWS - 1, 2, 2));
// Not used: ChartDataSource<String> ys3 = DataSources.fromStringCellRange(dataSheet, new CellRangeAddress(0, NUM_OF_ROWS - 1, 3, 3));
LineChartSeries series1 = data.addSeries(xs, ys1);
series1.setTitle("one");
LineChartSeries series2 = data.addSeries(xs, ys2);
series2.setTitle("two");
chart.plot(data, bottomAxis, leftAxis); // creating the basics of the graph
XSSFChart xssfChart = (XSSFChart) chart;
CTPlotArea plotArea = xssfChart.getCTChart().getPlotArea();
CTBoolean ctBool = CTBoolean.Factory.newInstance();
ctBool.setVal(true);
plotArea.getLineChartArray(0).getSerArray(0).addNewDLbls().setShowVal(ctBool);
plotArea.getLineChartArray(0).getSerArray(0).getDLbls().addNewShowLeaderLines();
plotArea.getLineChartArray(0).getSerArray(0).getDLbls().setShowLeaderLines(ctBool);
ctBool.setVal(false);
plotArea.getLineChartArray(0).getSerArray(0).getDLbls().setShowSerName(ctBool);
plotArea.getLineChartArray(0).getSerArray(0).getDLbls().setShowPercent(ctBool);
plotArea.getLineChartArray(0).getSerArray(0).getDLbls().setShowLegendKey(ctBool);
plotArea.getLineChartArray(0).getSerArray(0).getDLbls().setShowCatName(ctBool);
plotArea.getLineChartArray(0).getSerArray(0).getDLbls().setShowLeaderLines(ctBool);
plotArea.getLineChartArray(0).getSerArray(0).getDLbls().setShowBubbleSize(ctBool);
// Adding "markers" on each point
CTMarker ctMarker = CTMarker.Factory.newInstance();
ctMarker.setSymbol(CTMarkerStyle.Factory.newInstance());
for (CTLineSer ser : plotArea.getLineChartArray()[0].getSerArray()) {
ser.setMarker(ctMarker);
}
try{
FileOutputStream fileOut = new FileOutputStream("D:" + File.separator + "stack_v2.xlsx");
wb.write(fileOut);
fileOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Generating the following output
Output from the code
But what I want, is having the showLeaderLines option activated inside the CDTLbsls structure
See the following desired output:
Desired output
I need help on:
Clarifying Apache-POI classes involved (CDTLbl, CDTLbls, CTLine, DLbl & DLbls)
How to achieved the ShowLeaderLines functionality
How to set specific content rather than the value
Located them at a specific point of the graph (as you may see, I would like to add it close to the top)
In the end, I find it was not possible to achieve the same functionality as with MS Office 2016 because the libs are not enough developed.
Ways tried between others was modifying directly the XML output... but some tags are not available yet.

C# Deleting rows of excel sheet that contain variable not working

So below you will see the code im using to iterate through a excel spreadsheet and find every row that contains x. For some reason not only does the operation STOP at the very last row and not finish the operation, allowing me to save my edits and close the handle to excel, but also seems to be skipping rows. It will go through, say 25k rows that need to be deleted, yet only delete 12.5k. Im sure im doing something simple wrong here, so im hoping a few sets of eyes on it can spot my mistake. My code:
void startOperation()
{
Console.WriteLine("Beginning start operations..." + searchText);
Console.WriteLine("Opening Workbook: " + filePath);
// create excel-instance:
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
// open the concrete file:
Workbook xlWorkbook = xlApp.Workbooks.Open(#filePath);
//MessageBox.Show(filePath);
// select worksheet. NOT zero-based!!:
_Worksheet xlWorksheet = xlWorkbook.Sheets[1];
//MessageBox.Show(Convert.ToString(xlWorksheet.Name));
Microsoft.Office.Interop.Excel.Range range;
int numRows = xlWorksheet.UsedRange.Rows.Count;
numRowsDeleted = 0;
nullCounter = 0;
var percentageComp = new Decimal(.001);
//Parallel.For(1, numRows, new ParallelOptions { MaxDegreeOfParallelism = 1 }, i =>
for (currRow = 1; currRow <= numRows; currRow++)
{
percentageComp = ((decimal)currRow / (decimal)numRows) * 100;
Console.Clear();
Console.WriteLine("Number of Rows: " + numRows);
Console.WriteLine("Checking Row #: " + currRow);
Console.WriteLine("Number of Rows Deleted: " + numRowsDeleted);
Console.WriteLine("Percentage Comp: " + percentageComp.ToString("#.##"));
//Create Worksheet Range
range = (Microsoft.Office.Interop.Excel.Range)xlWorksheet.Cells[currRow, 2];
//MessageBox.Show(cellValue);
if (currRow == numRows)
{
closeOperation(xlApp, xlWorkbook);
break;
}
if (Convert.ToString(range.Value) != null) //if (cellValue != null || cellValue != "")
{
cellValue = Convert.ToString(range.Value);
//nullCounter = 0;
//MessageBox.Show("Cell Value: " + cellValue);
if (cellValue.Contains("MESSAGE NOT CONFIGURED"))
{
//MessageBox.Show("Cell Value: " + cellValue);
xlWorksheet.Rows[currRow].Delete(XlDeleteShiftDirection.xlShiftUp);
numRowsDeleted++;
//currRow++;
}
else
{
//currRow++;
}
}
else
{
//nullCounter++;
//currRow++;
}
//currRow++;
}
}
Again, your help is appreciated. Thanks!

Why does attempt to color ranges in a PivotTable have no effect (Aspose Cells)?

I'm trying to conditionally colorize ranges in a PivotTable like so:
private void ColorizeContractItemBlocks(List<string> contractItemDescs)
{
int FIRST_DESCRIPTION_ROW = 7;
int DESCRIPTION_COL = 0;
int ROWS_BETWEEN_DESCRIPTIONS = 4;
var pivot = pivotTableSheet.PivotTables[0];
var dataBodyRange = pivot.DataBodyRange;
int currentRowBeingExamined = FIRST_DESCRIPTION_ROW;
int rowsUsed = dataBodyRange.EndRow;
pivot.RefreshData();
pivot.CalculateData();
// Loop through PivotTable data, colorizing contract items
while (currentRowBeingExamined < rowsUsed)
{
Cell descriptionCell = pivotTableSheet.Cells[currentRowBeingExamined, DESCRIPTION_COL];
String desc = descriptionCell.Value.ToString();
if (contractItemDescs.Contains(desc))
{
// args are firstRow, firstColumn, totalRows, totalColumns
Range rangeToColorize = pivotTableSheet.Cells.CreateRange(
currentRowBeingExamined, 0,
ROWS_BETWEEN_DESCRIPTIONS, _grandTotalsColumnPivotTable + 2);
Style style = workBook.Styles[workBook.Styles.Add()];
style.BackgroundColor = CONTRACT_ITEM_COLOR;
StyleFlag styleFlag = new StyleFlag();
styleFlag.All = true;
rangeToColorize.ApplyStyle(style, styleFlag);
}
currentRowBeingExamined = currentRowBeingExamined + ROWS_BETWEEN_DESCRIPTIONS;
}
}
...but, although the if block is reached several times (such as where "rangeToColorize" spans A28:E31) it doesn't "take"; what is wrong with my styling or styleflagging or applying those?
UPDATE
Even when I changed it to this:
// Declare a style object.
Style style;
// Create/add the style object.
style = workBook.CreateStyle();
// To Set the fill color of the range, you may use ForegroundColor with
// Solid Pattern setting.
style.BackgroundColor = CONTRACT_ITEM_COLOR;
style.Pattern = BackgroundType.Solid;
// Create a StyleFlag object.
StyleFlag styleFlag = new StyleFlag();
// Make the corresponding attributes ON.
styleFlag.Font = true;
styleFlag.CellShading = true;
// Apply the style to the range.
rangeToColorize.ApplyStyle(style, styleFlag);
...based on the offical docs, it made no difference.
UPDATE 2
Even when I changed some very explicit code about one particular cell to this:
cell = pivotTableSheet.Cells[4, 0];
cell.PutValue(AnnualContractProductsLabel);
style = workBook.CreateStyle(); // cell.GetStyle();
style.HorizontalAlignment = TextAlignmentType.Center;
style.VerticalAlignment = TextAlignmentType.Center;
style.Font.IsBold = true;
pivotTableSheet.Cells.SetRowHeight(4, 25);
//style.BackgroundColor = CONTRACT_ITEM_COLOR;
style.ForegroundColor = CONTRACT_ITEM_COLOR;
pivotTableSheet.Cells[4, 0].SetStyle(style);
...IOW, changing "style = cell.GetStyle()" to "style = workBook.CreateStyle()" and "BackgroundColor" to "ForegroundColor", it does nothing; the cell in question is not colored.
UPDATE 3
Well, the (or an) odd thing is that the only way I've been able to color anything is in a manually generated "Grand Total" column:
As you can see, certain rows have been colorized, based on a condition. But only in that column, not across the entire row, as it should (theoretically, at least) be:
private void ColorizeContractItemBlocks(List<string> contractItemDescs)
{
int FIRST_DESCRIPTION_ROW = 7;
int DESCRIPTION_COL = 0;
int ROWS_BETWEEN_DESCRIPTIONS = 4;
var pivot = pivotTableSheet.PivotTables[0];
var dataBodyRange = pivot.DataBodyRange;
int currentRowBeingExamined = FIRST_DESCRIPTION_ROW;
int rowsUsed = dataBodyRange.EndRow;
pivot.RefreshData();
pivot.CalculateData();
// Loop through PivotTable data, colorizing contract items
while (currentRowBeingExamined < rowsUsed)
{
Cell descriptionCell = pivotTableSheet.Cells[currentRowBeingExamined, DESCRIPTION_COL];
String desc = descriptionCell.Value.ToString();
if (contractItemDescs.Contains(desc))
{
// args are firstRow, firstColumn, totalRows, totalColumns
Range rangeToColorize = pivotTableSheet.Cells.CreateRange(
currentRowBeingExamined, 0,
ROWS_BETWEEN_DESCRIPTIONS, _grandTotalsColumnPivotTable + 2);
// Declare a style object.
Style style;
// Create/add the style object.
style = workBook.CreateStyle();
style.ForegroundColor = CONTRACT_ITEM_COLOR; //Color.Red;
style.Pattern = BackgroundType.Solid;
// Create a StyleFlag object.
StyleFlag styleFlag = new StyleFlag();
// Make the corresponding attributes ON.
styleFlag.Font = true;
styleFlag.CellShading = true;
// Apply the style to the range.
rangeToColorize.ApplyStyle(style, styleFlag);
}
currentRowBeingExamined = currentRowBeingExamined + ROWS_BETWEEN_DESCRIPTIONS;
}
}
So that makes me think that a PivotTable cannot be colorized. Yet, even when I try to color a "plain old" cell like so:
cell = pivotTableSheet.Cells[4, 0];
cell.PutValue(AnnualContractProductsLabel);
style = workBook.CreateStyle();
style.HorizontalAlignment = TextAlignmentType.Center;
style.VerticalAlignment = TextAlignmentType.Center;
style.Font.IsBold = true;
pivotTableSheet.Cells.SetRowHeight(4, 25);
style.ForegroundColor = CONTRACT_ITEM_COLOR;
// Create a StyleFlag object.
StyleFlag styleFlag = new StyleFlag();
// Make the corresponding attributes ON.
styleFlag.Font = true;
styleFlag.CellShading = true;
// Apply the style to the cell
pivotTableSheet.Cells[4, 0].SetStyle(style, styleFlag);
...it doesn't work - the color is not added. Why does colorizing only work in the one circumstance, but not otherwise?
UPDATE 4
With this:
PivotTableCollection pivotTables = pivotTableSheet.PivotTables;
PivotTable pivotTable = pivotTables[0];
pivotTable.Format();
...I get, "No overload for method 'Format' takes 0 arguments."
...and also with simply this:
PivotTable.Format();
(capital "P", no "pivotTable" assigned), I get the same err msg.
UPDATE 5
Even with the following, based on the suggestion of another Aspose support person, it does nothing:
private void ColorizeContractItemBlocks(List<string> contractItemDescs)
{
int FIRST_DESCRIPTION_ROW = 7;
int DESCRIPTION_COL = 0;
int ROWS_BETWEEN_DESCRIPTIONS = 4;
var pivot = pivotTableSheet.PivotTables[0];
var dataBodyRange = pivot.DataBodyRange;
int currentRowBeingExamined = FIRST_DESCRIPTION_ROW;
int rowsUsed = dataBodyRange.EndRow;
pivot.RefreshData();
pivot.CalculateData();
// Loop through PivotTable data, colorizing contract items
while (currentRowBeingExamined < rowsUsed)
{
Cell descriptionCell = pivotTableSheet.Cells[currentRowBeingExamined, DESCRIPTION_COL];
String desc = descriptionCell.Value.ToString();
if (contractItemDescs.Contains(desc))
{
Style style;
style = workBook.CreateStyle();
style.ForegroundColor = CONTRACT_ITEM_COLOR; //Color.Red;
style.Pattern = BackgroundType.Solid;
StyleFlag styleFlag = new StyleFlag();
styleFlag.Font = true;
styleFlag.CellShading = true;
PivotTable pt = pivotTableSheet.PivotTables[0];
pt.Format(currentRowBeingExamined, 0, style); // test - does not work, either
pt.Format(currentRowBeingExamined, 1, style); // " "
//CellArea columnRange = pt.ColumnRange;
//for (int c = columnRange.StartColumn; c < columnRange.EndColumn; c++)
//{
// // pt.Format(columnRange.StartRow + 1, c, style);
// pt.Format(currentRowBeingExamined, c, style);
//}
}
currentRowBeingExamined = currentRowBeingExamined + ROWS_BETWEEN_DESCRIPTIONS;
}
}
UPDATE 6
I've got it pretty much working, now, with the following code:
private void ColorizeContractItemBlocks(List<string> contractItemDescs)
{
int FIRST_DESCRIPTION_ROW = 7;
int DESCRIPTION_COL = 0;
int ROWS_BETWEEN_DESCRIPTIONS = 4;
var pivot = pivotTableSheet.PivotTables[0];
var dataBodyRange = pivot.DataBodyRange;
int currentRowBeingExamined = FIRST_DESCRIPTION_ROW;
int rowsUsed = dataBodyRange.EndRow;
pivot.RefreshData();
pivot.CalculateData();
// Loop through PivotTable data, colorizing contract items
while (currentRowBeingExamined < rowsUsed)
{
Cell descriptionCell = pivotTableSheet.Cells[currentRowBeingExamined, DESCRIPTION_COL];
String desc = descriptionCell.Value.ToString();
if (contractItemDescs.Contains(desc))
{
Style style;
style = workBook.CreateStyle();
style.BackgroundColor = CONTRACT_ITEM_COLOR;
style.Pattern = BackgroundType.Solid;
StyleFlag styleFlag = new StyleFlag();
styleFlag.Font = true;
styleFlag.CellShading = true;
PivotTable pt = pivotTableSheet.PivotTables[0];
pt.Format(currentRowBeingExamined, 0, style);
pt.Format(currentRowBeingExamined, 1, style);
CellArea columnRange = pt.ColumnRange;
for (int c = columnRange.StartColumn; c <= columnRange.EndColumn; c++)
{
pt.Format(currentRowBeingExamined, c, style);
pt.Format(currentRowBeingExamined+1, c, style);
pt.Format(currentRowBeingExamined+2, c, style);
pt.Format(currentRowBeingExamined+3, c, style);
}
}
currentRowBeingExamined = currentRowBeingExamined + ROWS_BETWEEN_DESCRIPTIONS;
}
}
...but the second, third, and fourth rows of the Data column are not being colored:
Why not? How can I fix it?
UPDATE 7
I tried to get the elements of column B to color up, and tried changing this:
pt.Format(currentRowBeingExamined, 0, style);
pt.Format(currentRowBeingExamined, 1, style);
...to this:
pt.Format(currentRowBeingExamined, 0, style);
pt.Format(currentRowBeingExamined, 1, style);
pt.Format(currentRowBeingExamined, 2, style); // <= made no difference
pt.Format(currentRowBeingExamined, 3, style); // " "
...but it made no difference.
So then I wondered if the first two-line snippet above was necessary, but commenting those lines out caused columns A/0 and B/1 to not color up at all:
Here is the current code in context:
PivotTable pt = pivotTableSheet.PivotTables[0];
var style = workBook.CreateStyle();
while (currentRowBeingExamined < rowsUsed)
{
Cell descriptionCell = pivotTableSheet.Cells[currentRowBeingExamined, DESCRIPTION_COL];
String desc = descriptionCell.Value.ToString();
if (contractItemDescs.Contains(desc))
{
style.BackgroundColor = CONTRACT_ITEM_COLOR;
style.Pattern = BackgroundType.Solid;
pt.Format(currentRowBeingExamined, 0, style);
pt.Format(currentRowBeingExamined, 1, style);
//pt.Format(currentRowBeingExamined, 2, style); <= made no difference
//pt.Format(currentRowBeingExamined, 3, style);
CellArea columnRange = pt.ColumnRange;
for (int c = columnRange.StartColumn; c <= columnRange.EndColumn; c++)
{
pt.Format(currentRowBeingExamined, c, style);
pt.Format(currentRowBeingExamined+1, c, style);
pt.Format(currentRowBeingExamined+2, c, style);
pt.Format(currentRowBeingExamined+3, c, style);
}
}
currentRowBeingExamined = currentRowBeingExamined + ROWS_BETWEEN_DESCRIPTIONS;
}
So how can I get the colorization to span all the columns, including the "Total Purchases", "Sum of Average Price", and "Percentage of Total" cells?
Please change the following two lines
Style style = workBook.CreateStyle();
style.BackgroundColor = CONTRACT_ITEM_COLOR;
into
Style style = workBook.CreateStyle();
style.ForegroundColor= CONTRACT_ITEM_COLOR;
It should fix your issue. Let us know your feedback.
UPDATE 2
Please try one of the following two methods that are for PivotTable specifically
PivotTable.Format()
PivotTable.FormatAll()
UPDATE 5
For PivotTable.Format(), you should use Style.BackgroundColor property instead of Style.ForegroundColor property. So change your line
style.ForegroundColor = CONTRACT_ITEM_COLOR; //Color.Red;
to
style.BackgroundColor = CONTRACT_ITEM_COLOR; //Color.Red;
and it should fix your issue. Thank you.
Note: I am working as Developer Evangelist at Aspose

Resources