I want to create "stacked bar chart" using apache poi library. Need some documentation.
row1 = worksheet.createRow(r);
row['data'].flatten.each_with_index do |data, index|
cell = row1.createCell(index);
cell.setCellValue(data);
end
drawing = worksheet.createDrawingPatriarch();
anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 8, 20);
chart = drawing.createChart(anchor);
ctChart = chart.getCTChart();
ctPlotArea = ctChart.getPlotArea();
ctBarChart = ctPlotArea.addNewBarChart();
ctBoolean = ctBarChart.addNewVaryColors();
ctBoolean.setVal(true);
ctBarChart.addNewBarDir().setVal(STBarDir.BAR);
ctBarChart.addNewGrouping().setVal(STBarGrouping.STACKED);
ctBarSer = ctBarChart.addNewSer();
ctSerTx = ctBarSer.addNewTx();
ctStrRef = ctSerTx.addNewStrRef();
ctStrRef.setF("Sheet1!$A$#{r+1}");
ctBarSer.addNewIdx().setVal(r+1);
cttAxDataSource = ctBarSer.addNewCat();
ctStrRef = cttAxDataSource.addNewStrRef();
length = row['data'].flatten.length
ctStrRef.setF("Sheet1!$B$#{r+1}:$#{CellReference.convertNumToColString(length-1)}$#{r + 1}");
ctNumDataSource = ctBarSer.addNewVal();
ctNumRef = ctNumDataSource.addNewNumRef();
ctNumRef.setF("Sheet1!$B$#{r+1}:$#{CellReference.convertNumToColString(length-1)}$#{r+1}");
ctBarSer.addNewSpPr().addNewLn().addNewSolidFill().addNewSrgbClr().setVal([0,0,0]);
Using above code I am getting bar chart but need to convert to stacked bar chart.
enter image description here
While I can't tell you exactly what the magic incantation to make your chart work is, I can help you work through your issue.
If the type of chart you want to create is not supported by POI. You are going to have to create it manually. Seems you have a good start on that. You can find specification documents here http://www.ecma-international.org/publications/standards/Ecma-376.htm. POI uses the 1st edition of the spec.
While these documents are very good, you might need some help determining just how to structure the XML. The way I go about it is to create a simple document using Excel or Word, then rename the saved document as *.zip. Now you can inspect the xml package using Notepad++ or some other viewer.
Once you have something generated with POI, you can also view the resulting XML in a similar manner to se what the differences are if the results are not as expected.
Related
I am very new to using plotly in rstudio and have come up against a problem with mapping discrete colours (stored as hex codes in the field color) to each of the slices in my ids field.
I have included my code below:
df %>%
plot_ly(
color = I("black"),
marker = list(colors = ~color)) %>%
add_trace(ids = df$ids,
labels = df$labels,
parents = df$parents,
type = 'sunburst',
maxdepth = -1,
domain = list(column = 0)) %>%
layout(sunburstcolorway = df$color)
This is the resulting sunburst diagram I get using this code, which is obviously not ideal:
Ideally the first four levels would have the same colour, and then different hex colour codes are used for slices that are labelled "Poor","Moderate","GwC" or "Good".
A csv file of my data frame used above is available here.
I finally managed to nut out how to map my colour field to the background colours on the sunburst chart - have updated the code in original post. All that was required was to insert the following code segment:
plot_ly(
marker = list(colors = ~color))
Below is the output chart:
Can anyone share working code that draws a timeseries (e.g x=dates,y=numeric values) chart with POI 4.0.0? I am trying to draw a 2-line chart that share dates on the X axis with POI 4.0.0
but this code:
...
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 10, 15);
XSSFChart chart = drawing.createChart(anchor);
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.TOP_RIGHT);
// Use a category axis for the bottom axis.
XDDFCategoryAxis bottomAxis =
chart.createCategoryAxis(AxisPosition.BOTTOM);
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
int chartStartRow = SHEET_START_ROW + 1;
int chartEndRow = chartStartRow + mergedData.size() - 1;
// This is selecting data from a column of dates
XDDFDataSource<String> xs = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(chartStartRow, chartEndRow, 0, 0));
// This is time series 1
XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(chartStartRow, chartEndRow, 1, 1));
// This is time series 2
XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(chartStartRow, chartEndRow, 2, 2));
XDDFChartData data = chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
data.addSeries(xs, ys1);
data.addSeries(xs, ys2);
chart.plot(data);
results in exception:
Caused by: java.lang.NullPointerException: null
at org.apache.poi.xddf.usermodel.chart.XDDFChartData$Series.fillStringCache(XDDFChartData.java:260) ~[poi-ooxml-4.0.0.jar:4.0.0]
at org.apache.poi.xddf.usermodel.chart.XDDFChartData$Series.plot(XDDFChartData.java:153) ~[poi-ooxml-4.0.0.jar:4.0.0]
at org.apache.poi.xddf.usermodel.chart.XDDFChart.plot(XDDFChart.java:287) ~[poi-ooxml-4.0.0.jar:4.0.0]
I would even appreciate code snippets for older POI versions, as I suspect POI 4.0.0 is buggy. Thanks
Alex's comment to treat dates as number is correct, but POI 4.0.0 charts are not ready yet and you need to apply the code hacks from here:
Problem running official examples LineChars and ScatterChart with Apache POI 4.0
I want to add Annotations comment in existing PDF file using iTextSharp with C#.
Please give sample code to add Annotations in existing PDF file.
Here PS Script for my Annotation:
[/Contents (My Text contents) /Rect [100 600 150 550] /SrcPg 1 /Title (My Title text) /Color [0 0 1] /Subtype /Caret /ANN pdfmark
The iText(Sharp) example TimetableAnnotations1.java / TimetableAnnotations1.cs from chapter 7 of iText in Action — 2nd Edition shows how to add annotations to existing PDFs in general.
The central code is (in the C# example):
rect = GetPosition(screening);
annotation = PdfAnnotation.CreateText(
stamper.Writer, rect, movie.MovieTitle,
string.Format(INFO, movie.Year, movie.Duration),
false, "Help"
);
annotation.Color = WebColors.GetRGBColor(
"#" + movie.entry.category.color
);
stamper.AddAnnotation(annotation, page);
where stamper is a PdfStamper working on your PDF file; movie is a data structure the example retrieves title, text and color of the annotation from.
PdfAnnotation offers multiple other Create... methods to create other types of annotations.
rect = GetPosition(screening);
can someone plz explain why is this is used..is there any way to find the current cursor position (top,bottom,height,width)
as with the annotation,
Document doc = new Document(PageSize.A4, 50, 50, 50, 50);
PdfWriter writer = PdfWriter.GetInstance(doc, new FileStream(#"C:\Users\Asus\Desktop\Test.pdf", FileMode.OpenOrCreate));
doc.AddDocListener(writer);
doc.Open();
doc.Add(new Annotation("annotation", "The text displayed in the sticky note", 100f, 500f, 200f, 600f));
doc.Close();
this works fine to me..
I am using a BarClustered chart using EPPlus for Excel Package in C#. I am able to generate the bar chart as required. Only problem I am facing is that when I have a negative value, the bar does not show any color. It would be as if a transparent bar with only the border.
I am facing this issue with Excel 2013. However this works fine in Excel 2007.
ExcelWorksheet wsDataSource = xlPackage.Workbook.Worksheets.Add("DataSource");
wsDataSource.Hidden = eWorkSheetHidden.VeryHidden;
var namedStyle = xlPackage.Workbook.Styles.CreateNamedStyle("HyperLink");
namedStyle.Style.Font.UnderLine = true;
namedStyle.Style.Font.Color.SetColor(Color.Blue);
//Here I iterate through an array and populate the wsDataSource values as below starting from 3rd row:
Feb 2000 5000
March -2000 2770
April 4000 4643
var chart = worksheet.Drawings.AddChart("Chart", OfficeOpenXml.Drawing.Chart.eChartType.BarClustered);
//row is the offset int variable
chart.SetPosition(row + 2, 0, 0, 10);
chart.SetSize(750, 30);
chart.Title.Text = "Data Graph";
chart.Legend.Position = eLegendPosition.Top;
var barChart = chart as ExcelBarChart;
barChart.DataLabel.ShowValue = true;
var mySeries = chart.Series.Add(wsDataSource.Cells[3, 2, intDataRow - 1, 2], wsDataSource.Cells[3, 1, intDataRow - 1, 1]);
mySeries.Header = "Current Year";
//isPreviousYearDataAvailable is a boolean which indicates if previous year data for the user is available.
if (isPreviousYearDataAvailable)
{
var mySeries2 = chart.Series.Add(wsDataSource.Cells[3, 3, intDataRow, 3], wsDataSource.Cells[3, 1, intDataRow - 1, 1]);
mySeries2.Header = "Previous Year"
}
Below is the image I get for negative values when opening using Excel 2013.
It appears that EPPlus doesn't have support for the "invertIfNegative" tag for data series. You might have to contact the authors for help, or add in the feature yourself. The Open XML specs state that:
This element specifies the parent element shall invert its colors if the value is negative.
Also:
A value of on, 1, or true specifies that the property is applied. This is the default value for this attribute, and is implied when the parent element is present, but this attribute is omitted.
Since EPPlus doesn't render this tag, the default value is used, which is "true". The "parent element" in this case is the data series XML element. So this means colors will be inverted if the cell value is negative. Hence the transparent color you see.
I have found that different versions of Excel obey the Open XML specs slightly differently. Excel 2013 appears to obey more strictly to the Open XML specs, which is why you get a transparent color. Excel 2007 probably ignored the absent "invertIfNegative" tag (meaning if absent, you don't want to have anything to do with inverting colors and so on, and so Excel will just render the color). In this sense, Excel 2007 is more forgiving of mistakes, which may or may not be a good thing.
Adding <c:invertIfNegative val="0"/> to the XML manually seemed to work for me:
System.Xml.XmlNode invertIfNegativeNode = chart.ChartXml.CreateElement(
"c", "invertIfNegative", "http://schemas.openxmlformats.org/drawingml/2006/chart");
System.Xml.XmlAttribute invertIfNegativeAttribute = chart.ChartXml.CreateAttribute("val");
invertIfNegativeAttribute.Value = "0";
invertIfNegativeNode.Attributes.Append(invertIfNegativeAttribute);
chart.ChartXml.DocumentElement["c:chart"]["c:plotArea"]["c:barChart"]["ser"].AppendChild(invertIfNegativeNode);
Adding to this old post, I hit the same problem in Excel 2016 but was unable to resolve it with #Saxon Druce answer directly. When I examine chart1.xml behind the Excel, only ser contains invertIfNegative and setting it's val attribute to 0 does not apply to any bar (still remain inverted / transparent). When I open the file in Excel and uncheck Series Option/Invert if negative option and reopen chart1.xml, I found each and every bar dPt is inject with invertIfNegative node.
So I modified #Saxon Druce answer a bit, create and append invertIfNegative node to each bar's dPt (2nd arrow) instead of appending to parent node ser (1st arrow). Then the ExcelBarChart turns out ok with all bars colored (not inverted).
I banged my head for hours so hopefully this help someone with Excel 2016.
var nsuri = chartXml.DocumentElement.NamespaceURI;
var dPt = chartXml.CreateNode(XmlNodeType.Element, "dPt", nsuri);
var invertIfNegative = chartXml.CreateNode(XmlNodeType.Element, "invertIfNegative", nsuri);
var att = chartXml.CreateAttribute("val", nsuri);
att.Value = "0";
invertIfNegative.Attributes.Append(att);
dPt.AppendChild(invertIfNegative);
// Other xml changes
var idx = chartXml.CreateNode(XmlNodeType.Element, "idx", nsuri);
att = chartXml.CreateAttribute("val", nsuri);
att.Value = i.ToString();
idx.Attributes.Append(att);
dPt.AppendChild(idx);
I have a similar problem to this post (UIButton: Add gradient layer and title is not shown anymore - how to fix?) but his solution did not work for me. First things first, I'm somewhat new to MonoTouch, but have never gone as far as customizing the out of the box controls.
I am trying to add a gradient to my button, but when I do so, the gradient looks exactly as I want, but the text is covered (I set the opacity of my gradient to .5 to test). I have a storyboard in which I have visually designed the interface, but want to tweak a few things.
Here is my code:
var gradient = new CAGradientLayer();
gradient.Frame = getStartedButton.Layer.Bounds;
gradient.Colors = new MonoTouch.CoreGraphics.CGColor[]
{
UIColor.FromRGB (23, 55, 94).CGColor,
UIColor.FromRGB (33, 81, 141).CGColor
};
getStartedButton.Layer.AddSublayer(gradient);
getStartedButton.Layer.CornerRadius = 10;
getStartedButton.Layer.BorderColor = UIColor.White.CGColor;
getStartedButton.Layer.BorderWidth = 1;
getStartedButton.VerticalAlignment = UIControlContentVerticalAlignment.Center;
getStartedButton.Font = UIFont.FromName("Helvetica", 12);
getStartedButton.SetTitleColor(UIColor.White, UIControlState.Normal);
getStartedButton.SetTitle("Get Started", UIControlState.Normal);
Embarrassing, but it was simply a matter of changing the type of button to custom in XCode.