OpenXLSX/Examples/Demo10.cpp

541 lines
30 KiB
C++

#include <cmath>
#include <iostream>
#include <string>
#include <OpenXLSX.hpp>
#include <external/pugixml/pugixml.hpp>
bool nowide_status()
{
#ifdef ENABLE_NOWIDE
return true;
#else
return false;
#endif
}
using namespace std;
using namespace OpenXLSX;
int main()
{
cout << "********************************************************************************\n";
cout << "DEMO PROGRAM #10: XLStyles Usage and XLSheet conditional formatting\n";
cout << "********************************************************************************\n";
std::cout << "nowide is " << ( nowide_status() ? "enabled" : "disabled" ) << std::endl;
/*
* TODO: align XLStyles.cpp with known documentation of xl/styles.xml as far as support is desired
* * XLAlignmentStyle: check / throw if vertical alignments are used as horizontal and vice versa
* * XLStyles ::create functions: implement good default style properties for all styles
* * support "colors"
* * support "dxfs"
* * support "tableStyles"
* TODO TBD: permit setting a format reference for shared strings
*
* DONE: XLFills: support patternFill patternType (XLFillPattern)
* DONE: XLFonts: support scheme major/minor/none (<font><scheme val="major"/></font>)
* DONE: XLFonts: support vertical align run style (<font><vertAlign val="subscript"/></font>)
* DONE: XLFills: support gradientFill
* DONE: support complete for: "borders", "cellStyles", "cellStyleXfs", "cellXfs", "numFmts"
* DONE: support nearly complete (exceptions above) for: "fonts"
* DONE: support for xfId / setXfId in XLStyles::cellFormats, but not(!) in XLStyles::cellStyleFormats
* DONE: format support for XLCells (cellFormat / setCellFormat)
* DONE: format support for XLRows: <row> attributes s (same as cell attribute) and customFormat (=true/false)
* XLWorksheet::setRowFormat overwrites existing cell formats, and
* row format is then used by OpenXLSX for new cells created in that row
* DONE: format support for XLColumns: <col> attributes style (same as cell attribute s)
* XLWorksheet::setColumnFormat overwrites existing cell formats, and
* column format is then used by OpenXLSX as default for new cells created in that column when they do not have a row style
* DONE: update style elements "count" attribute for all arrays when saving
*/
// create new workbook
XLDocument doc{};
doc.create("./Demo10.xlsx", XLForceOverwrite);
// doc.open("./Demo10.xlsx");
std::cout << "doc.name() is " << doc.name() << std::endl;
XLNumberFormats & numberFormats = doc.styles().numberFormats();
XLFonts & fonts = doc.styles().fonts();
XLFills & fills = doc.styles().fills();
XLBorders & borders = doc.styles().borders();
XLCellFormats & cellStyleFormats = doc.styles().cellStyleFormats();
XLCellFormats & cellFormats = doc.styles().cellFormats();
XLCellStyles & cellStyles = doc.styles().cellStyles();
XLWorksheet wks = doc.workbook().worksheet(1);
XLStyleIndex cellFormatIndexA2 = wks.cell("A2").cellFormat(); // get index of cell format
XLStyleIndex fontIndexA2 = cellFormats[ cellFormatIndexA2 ].fontIndex(); // get index of used font
XLStyleIndex newFontIndex = fonts.create( fonts[ fontIndexA2 ] ); // create a new font based on used font
XLStyleIndex newCellFormatIndex // create a new cell format
= cellFormats.create( cellFormats[ cellFormatIndexA2 ] ); // based on used format
cellFormats[ newCellFormatIndex ].setFontIndex( newFontIndex ); // assign the new font to the new cell format
wks.cell("A2").setCellFormat( newCellFormatIndex ); // assign the new cell format to the cell
// // change the new font style:
fonts[ newFontIndex ].setFontName("Arial");
fonts[ newFontIndex ].setFontSize(14);
XLColor red ( "ffff0000" );
XLColor green ( "ff00ff00" );
XLColor blue ( "ff0000ff" );
XLColor yellow( "ffffff00" );
fonts[ newFontIndex ].setFontColor( green );
fonts[ newFontIndex ].setBold(); // bold
fonts[ newFontIndex ].setItalic(); // italic
fonts[ newFontIndex ].setStrikethrough(); // strikethrough
fonts[ newFontIndex ].setUnderline(XLUnderlineDouble); // underline: XLUnderlineSingle, XLUnderlineDouble, XLUnderlineNone
fonts[ newFontIndex ].setUnderline(XLUnderlineNone); // TEST: un-set the underline status
cellFormats[ newCellFormatIndex ].setApplyFont( true ); // apply the font (seems to do nothing)
wks.cell("A25" ) = "42"; // NEW functionality: XLCellAssignable now has a direct value assignment overload
std::cout << "wks A25 value is " << wks.cell("A25" ) << std::endl;
XLCellRange cellRange = wks.range("A3", "Z10"); // NEW functionality: range based on cell reference strings
std::cout << "range " << cellRange.address() // NEW: cell range address
<< " with top left " << cellRange.topLeft().address() // NEW: cell range topLeft cell reference
<< " and bottom right " << cellRange.bottomRight().address() // NEW: cell range bottomRight cell reference
<< " contains " << cellRange.numRows() << " rows, " << cellRange.numColumns() << " columns" << std::endl;
cellRange = wks.range("A1:XFD100"); // NEW functionality: range based on range reference
std::cout << "range " << cellRange.address() << " contains " << cellRange.numRows() << " rows, " << cellRange.numColumns() << " columns" << std::endl;
XLStyleIndex fontBold = fonts.create();
fonts[ fontBold ].setBold();
XLStyleIndex boldDefault = cellFormats.create();
cellFormats[ boldDefault ].setFontIndex( fontBold );
cellRange = wks.range("A5:Z5");
cellRange = "this is a bold range"; // NEW functionality: XLCellRange now has a direct value assignment overload
cellRange.setFormat( boldDefault ); // NEW functionality: XLCellRange supports setting format for all cells in the range
XLStyleIndex fontItalic = fonts.create();
fonts[ fontItalic ].setItalic();
XLStyleIndex italicDefault = cellFormats.create();
cellFormats[ italicDefault ].setFontIndex( fontItalic );
cellRange = wks.range("E1:E100");
cellRange = "this is an italic range";
cellRange.setFormat( italicDefault );
cellRange = wks.range("A10:Z11");
cellRange = "lalala"; // create cells if they do not exist by assigning values to them
XLRow row = wks.row(10);
row.cells() = "this is an italic row"; // NEW functionality: overwrite value for all *existing* cells in row
wks.setRowFormat( row.rowNumber(), italicDefault ); // NEW functionality: set format for all (existing) cells in row, and row format to be used as default for future cells
cellRange = wks.range("J1:J100");
cellRange = "this is a bold column";
XLColumn col = wks.column("J"); // NEW functionality: XLWorksheet::column now supports getting a column from a column reference
wks.setColumnFormat( XLCellReference::columnAsNumber("J"), boldDefault ); // NEW functionality: set format for all (existing) cells in column, and column format to be used as default for future cells
wks.setRowFormat( 11, newCellFormatIndex ); // set row 11 to bold italic underline strikethrough font with color as formatted above
XLStyleIndex redFormat = cellFormats.create( cellFormats[ newCellFormatIndex ] );
XLStyleIndex redFont = fonts.create();
fonts[ redFont ].setFontColor( red );
cellFormats[ redFormat ].setFontIndex( redFont );
cellRange = wks.range("B2:P5");
cellRange = "red range";
wks.cell(cellRange.topLeft()).value() = "red range " + cellRange.address() + " top left cell";
wks.cell(cellRange.bottomRight()).value() = "red range " + cellRange.address() + " bottom right cell";
cellRange.setFormat( redFormat );
// // get the relevant style objects for easy access
// XLCellFormats & cellFormats = doc.styles().cellFormats();
// XLFonts & fonts = doc.styles().fonts();
// XLFills & fills = doc.styles().fills();
XLCellRange myCellRange = wks.range("B20:P25"); // create a new range for formatting
myCellRange = "TEST COLORS"; // write some values to the cells so we can see format changes
XLStyleIndex baseFormat = wks.cell("B20").cellFormat(); // determine the style used in B20
XLStyleIndex newCellStyle = cellFormats.create( cellFormats[ baseFormat ] ); // create a new style based on the style in B20
XLStyleIndex newFontStyle = fonts.create(fonts[ cellFormats[ baseFormat ].fontIndex() ]); // create a new font style based on the used font
XLStyleIndex newFillStyle = fills.create(fills[ cellFormats[ baseFormat ].fillIndex() ]); // create a new fill style based on the used fill
fonts[ newFontStyle ].setFontColor( green );
cellFormats[ newCellStyle ].setFontIndex( newFontStyle );
fills[ newFillStyle ].setPatternType ( XLPatternNone );
fills[ newFillStyle ].setPatternType ( XLPatternSolid );
// fills[ newFillStyle ].setPatternType ( XLPatternMediumGray );
// fills[ newFillStyle ].setPatternType ( XLPatternDarkGray );
// fills[ newFillStyle ].setPatternType ( XLPatternLightGray );
// fills[ newFillStyle ].setPatternType ( XLPatternDarkHorizontal );
// fills[ newFillStyle ].setPatternType ( XLPatternDarkVertical );
// fills[ newFillStyle ].setPatternType ( XLPatternDarkDown );
// fills[ newFillStyle ].setPatternType ( XLPatternDarkUp );
// fills[ newFillStyle ].setPatternType ( XLPatternDarkGrid );
// fills[ newFillStyle ].setPatternType ( XLPatternDarkTrellis );
// fills[ newFillStyle ].setPatternType ( XLPatternLightHorizontal );
// fills[ newFillStyle ].setPatternType ( XLPatternLightVertical );
// fills[ newFillStyle ].setPatternType ( XLPatternLightDown );
// fills[ newFillStyle ].setPatternType ( XLPatternLightUp );
// fills[ newFillStyle ].setPatternType ( XLPatternLightGrid );
// fills[ newFillStyle ].setPatternType ( XLPatternLightTrellis );
// fills[ newFillStyle ].setPatternType ( XLPatternGray125 );
// fills[ newFillStyle ].setPatternType ( XLPatternGray0625 );
fills[ newFillStyle ].setColor ( yellow );
fills[ newFillStyle ].setBackgroundColor( blue ); // blue, setBackgroundColor only makes sense with gradient fills
cellFormats[ newCellStyle ].setFillIndex( newFillStyle );
myCellRange.setFormat( newCellStyle ); // assign the new format to the full range of cells
// XLFill -> XLGradientFill test:
myCellRange = wks.range("B30:P35"); // create a new range for formatting
myCellRange = "TEST GRADIENT"; // write some values to the cells so we can see format changes
baseFormat = wks.cell("B30").cellFormat(); // determine the style used in B20
newCellStyle = cellFormats.create( cellFormats[ baseFormat ] ); // create a new style based on the style in B20
XLStyleIndex testGradientIndex = fills.create(fills[ cellFormats[ baseFormat ].fillIndex() ]); // create a new fill style based on the used fill
fills[ testGradientIndex ].setFillType( XLPatternFill ); // set the "wrong" fill type
fills[ testGradientIndex ].setFillType( XLGradientFill, XLForceFillType ); // override that with a gradientFill
fills[ testGradientIndex ].setGradientType( XLGradientLinear ); // the gradient type
// configure the gradient stops
XLGradientStops stops = fills[ testGradientIndex ].stops();
// first XLGradientStop
XLStyleIndex stopIndex = stops.create();
XLDataBarColor stopColor = stops[ stopIndex ].color();
stops[ stopIndex ].setPosition(0.1);
stopColor.setRgb( green );
// stopColor.setTint( 1.01 );
// stopColor.setAutomatic();
// stopColor.setIndexed( 77 );
// stopColor.setTheme( 79 );
// second XLGradientStop
stopIndex = stops.create(stops[stopIndex]); // create another stop using previous stop as template
stopColor.set( yellow );
stops[ stopIndex ].setPosition(0.5);
cellFormats[ newCellStyle ].setFillIndex( testGradientIndex );
myCellRange.setFormat( newCellStyle ); // assign the new format to the full range of cells
// ===== BEGIN cell borders demo
XLStyleIndex borderFormat = 0; // scope declaration
{
// create a new cell format based on the current C3 format & assign it back to C3
XLStyleIndex borderedCellFormat = cellFormats.create( cellFormats[ wks.cell("C7").cellFormat() ] );
wks.cell("C7").setCellFormat( borderedCellFormat );
wks.cell("C7") = "borders demo";
// ===== Create a new border format style & assign it to the new cell format
borderFormat = borders.create();
// NOTE: the new border format uses a default (empty) borders object to demonstrate OpenXLSX ordered inserts.
// Using an existing border style as a template would copy the OpenXLSX default border style which
// already contains elements in the correct sequence, so that inserts could not be demonstrated.
cellFormats[ borderedCellFormat ].setBorderIndex( borderFormat );
borders[ borderFormat ].setDiagonalUp( false ); // setting this to true will apply the diagonal line style
borders[ borderFormat ].setDiagonalDown( true ); // - both diagonals can be applied simultaneously, but only with the same style
borders[ borderFormat ].setOutline( true ); // not sure if this is needed at all
// ===== Insert lines in a "wrong" sequence that MS Office would refuse to accept, to demonstrate XLStyles ordered inserting capability
borders[ borderFormat ].setHorizontal( XLLineStyleHair, XLColor( "ff446688" ) );
borders[ borderFormat ].setVertical ( XLLineStyleDouble, XLColor( "ff443322" ) );
borders[ borderFormat ].setDiagonal ( XLLineStyleThick, XLColor( "ff332222" ), -0.25 );
borders[ borderFormat ].setBottom ( XLLineStyleDotted, XLColor( "ff222222" ), 0.25 );
borders[ borderFormat ].setTop ( XLLineStyleDashed, XLColor( "ff114444" ) );
borders[ borderFormat ].setRight ( XLLineStyleMedium, XLColor( "ff113333" ) );
borders[ borderFormat ].setLeft ( XLLineStyleThin, XLColor( "ff112222" ) );
std::cout << "#1 borders[ " << borderFormat << " ] summary: " << borders[ borderFormat ].summary() << std::endl;
// test additional line styles with setter function:
borders[ borderFormat ].setLine ( XLLineVertical, XLLineStyleSlantDashDot, XLColor( XLDefaultFontColor ) );
borders[ borderFormat ].setLine ( XLLineDiagonal, XLLineStyleMediumDashDotDot, XLColor( XLDefaultFontColor ), -1.0 );
borders[ borderFormat ].setLine ( XLLineBottom, XLLineStyleDashDotDot, XLColor( XLDefaultFontColor ), -0.1 );
borders[ borderFormat ].setLine ( XLLineTop, XLLineStyleMediumDashDot, green );
borders[ borderFormat ].setLine ( XLLineRight, XLLineStyleDashDot, XLColor( XLDefaultFontColor ), 1.0 );
borders[ borderFormat ].setLine ( XLLineLeft, XLLineStyleMediumDashed, XLColor( XLDefaultFontColor ) );
std::cout << "#2 borders[ " << borderFormat << " ] summary: " << borders[ borderFormat ].summary() << std::endl;
// test direct access to line properties (read: the XLDataBarColor)
XLLine leftLine = borders[ borderFormat ].left();
XLDataBarColor leftLineColor = leftLine.color();
leftLineColor.setRgb( blue );
leftLineColor.setTint( -0.2 );
leftLineColor.setAutomatic();
leftLineColor.setIndexed( 606 );
leftLineColor.setTheme( 707 );
std::cout << "#2 borders, leftLine summary: " << leftLine.summary() << std::endl;
// unset some properties
leftLineColor.setTint( -0.1 );
leftLineColor.setAutomatic( false );
leftLineColor.setIndexed( 0 );
leftLineColor.setTheme( XLDeleteProperty );
// NOTE: XLDeleteProperty can be used to remove a property from XML where a value of 0 would not accomplish the same
// formatting. Currently, only XLDataBarColor::setTheme supports this functionality. More can be added as properties
// are discovered that have the same problem (theme="" still overrides e.g. the line color)
std::cout << "#2 borders, leftLineColor summary: " << leftLineColor.summary() << std::endl;
}
// ===== END cell borders demo ===== //
// enable testBasics = true to create/modify at least one entry in each known styles array
// disable testBasics = false to stop the demo execution here and save the document
bool testBasics = false;
// CAUTION: setting testBasics = true will cause MS Excel to complain about document errors
// the purpose of this scope is to prove desired modification of the underlying XML
// tags for direct inspection with unzip + xmllint + text editor.
// The testBasics scope makes no attempt to generate meaningful or consistent style information.
if( testBasics ) {
std::cout << " numberFormats.count() is " << numberFormats.count() << std::endl;
std::cout << " fonts.count() is " << fonts.count() << std::endl;
std::cout << " fills.count() is " << fills.count() << std::endl;
std::cout << " borders.count() is " << borders.count() << std::endl;
std::cout << "cellStyleFormats.count() is " << cellStyleFormats.count() << std::endl;
std::cout << " cellFormats.count() is " << cellFormats.count() << std::endl;
std::cout << " cellStyles.count() is " << cellStyles.count() << std::endl;
// enable createAll = true to create a new entry in each known styles array and modify that
// disable createAll = false to modify the last entry in each styles array instead
bool createAll = true;
XLStyleIndex nodeIndex;
nodeIndex = ( createAll ? numberFormats.create() : numberFormats.count() - 1 );
numberFormats[ nodeIndex ].setNumberFormatId( 15 );
numberFormats[ nodeIndex ].setFormatCode( "fifteen" );
std::cout << "numberFormats[ " << nodeIndex << " ] summary: " << numberFormats[ nodeIndex ].summary() << std::endl;
nodeIndex = ( createAll ? fonts.create() : fonts.count() - 1 );
fonts[ nodeIndex ].setFontName( "Twelve" );
fonts[ nodeIndex ].setFontCharset( 13 );
fonts[ nodeIndex ].setFontFamily( 14 );
fonts[ nodeIndex ].setFontSize( 15 );
fonts[ nodeIndex ].setFontColor( XLColor( XLDefaultFontColor ) );
fonts[ nodeIndex ].setBold(); // bold
fonts[ nodeIndex ].setItalic(); // italic
fonts[ nodeIndex ].setStrikethrough(); // strikethrough
fonts[ nodeIndex ].setUnderline(XLUnderlineDouble); // underline: XLUnderlineSingle, XLUnderlineDouble, XLUnderlineNone
fonts[ nodeIndex ].setScheme(XLFontSchemeMajor);
// fonts[ nodeIndex ].setScheme(XLFontSchemeMinor);
// fonts[ nodeIndex ].setScheme(XLFontSchemeNone);
// fonts[ nodeIndex ].setScheme(XLFontSchemeInvalid);
fonts[ nodeIndex ].setVertAlign(XLSubscript);
// fonts[ nodeIndex ].setVertAlign(XLBaseline);
// fonts[ nodeIndex ].setVertAlign(XLSuperscript);
// fonts[ nodeIndex ].setVertAlign(XLVerticalAlignRunInvalid);
fonts[ nodeIndex ].setOutline();
fonts[ nodeIndex ].setShadow();
fonts[ nodeIndex ].setCondense();
fonts[ nodeIndex ].setExtend();
std::cout << "fonts[ " << nodeIndex << " ] summary: " << fonts[ nodeIndex ].summary() << std::endl;
// XLFill -> XLPatternFill test:
nodeIndex = ( createAll ? fills.create() : fills.count() - 1 );
fills[ nodeIndex ].setFillType( XLPatternFill );
fills[ nodeIndex ].setPatternType( XLPatternSolid );
// fills[ nodeIndex ].setPatternType( XLPatternTypeInvalid );
fills[ nodeIndex ].setColor ( XLColor( XLDefaultPatternFgColor ) );
fills[ nodeIndex ].setBackgroundColor( XLColor( XLDefaultPatternBgColor ) );
// output summary of previously created style with a gradient fill
std::cout << "fills[ " << testGradientIndex << " ] summary: " << fills[ testGradientIndex ].summary() << std::endl;
// output summary of newly created style
std::cout << "fills[ " << nodeIndex << " ] summary: " << fills[ nodeIndex ].summary() << std::endl;
nodeIndex = ( createAll ? cellStyleFormats.create() : cellStyleFormats.count() - 1 );
cellStyleFormats[ nodeIndex ].setNumberFormatId( 5 );
cellStyleFormats[ nodeIndex ].setFontIndex( 6 );
cellStyleFormats[ nodeIndex ].setFillIndex( 7 );
cellStyleFormats[ nodeIndex ].setBorderIndex( 8 );
cellStyleFormats[ nodeIndex ].setApplyFont(true);
cellStyleFormats[ nodeIndex ].setApplyFill(false);
cellStyleFormats[ nodeIndex ].setApplyBorder(false);
cellStyleFormats[ nodeIndex ].setApplyAlignment(true);
cellStyleFormats[ nodeIndex ].setApplyProtection(false);
cellStyleFormats[ nodeIndex ].setLocked(true);
cellStyleFormats[ nodeIndex ].setHidden(false);
cellStyleFormats[ nodeIndex ].alignment(XLCreateIfMissing).setHorizontal(XLAlignRight);
cellStyleFormats[ nodeIndex ].alignment(XLCreateIfMissing).setVertical(XLAlignCenter);
cellStyleFormats[ nodeIndex ].alignment(XLCreateIfMissing).setTextRotation(255);
cellStyleFormats[ nodeIndex ].alignment(XLCreateIfMissing).setWrapText(true);
cellStyleFormats[ nodeIndex ].alignment(XLCreateIfMissing).setIndent(256);
cellStyleFormats[ nodeIndex ].alignment(XLCreateIfMissing).setRelativeIndent(-255);
cellStyleFormats[ nodeIndex ].alignment(XLCreateIfMissing).setJustifyLastLine(true);
cellStyleFormats[ nodeIndex ].alignment(XLCreateIfMissing).setShrinkToFit(false);
cellStyleFormats[ nodeIndex ].alignment(XLCreateIfMissing).setReadingOrder(XLReadingOrderLeftToRight);
try { cellStyleFormats[ nodeIndex ].setXfId(9); } // TEST: this should throw
catch (XLException const & e) {
std::cout << "cellStyleFormats NOMINAL EXCEPTION: " << e.what() << std::endl;
}
try { (void) cellStyleFormats[ nodeIndex ].xfId(); } // TEST: this should throw
catch (XLException const & e) {
std::cout << "cellStyleFormats NOMINAL EXCEPTION: " << e.what() << std::endl;
}
std::cout << "cellStyleFormats[ " << nodeIndex << " ] summary: " << cellStyleFormats[ nodeIndex ].summary() << std::endl;
nodeIndex = ( createAll ? cellFormats.create() : cellFormats.count() - 1 );
cellFormats[ nodeIndex ].setNumberFormatId( 22 );
cellFormats[ nodeIndex ].setFontIndex( 23 );
cellFormats[ nodeIndex ].setFillIndex( 24 );
cellFormats[ nodeIndex ].setBorderIndex( 25 );
cellFormats[ nodeIndex ].setApplyNumberFormat(true);
cellFormats[ nodeIndex ].setApplyFont(false);
cellFormats[ nodeIndex ].setApplyFill(true);
cellFormats[ nodeIndex ].setApplyBorder(true);
cellFormats[ nodeIndex ].setApplyAlignment(false);
cellFormats[ nodeIndex ].setApplyProtection(true);
cellFormats[ nodeIndex ].setQuotePrefix(true);
cellFormats[ nodeIndex ].setPivotButton(true);
cellFormats[ nodeIndex ].setLocked(false);
cellFormats[ nodeIndex ].setHidden(true);
cellFormats[ nodeIndex ].alignment(XLCreateIfMissing).setHorizontal(XLAlignGeneral);
cellFormats[ nodeIndex ].alignment(XLCreateIfMissing).setVertical(XLAlignTop);
cellFormats[ nodeIndex ].alignment(XLCreateIfMissing).setTextRotation(370);
cellFormats[ nodeIndex ].alignment(XLCreateIfMissing).setWrapText(false);
cellFormats[ nodeIndex ].alignment(XLCreateIfMissing).setIndent(37);
cellFormats[ nodeIndex ].alignment(XLCreateIfMissing).setShrinkToFit(true);
cellFormats[ nodeIndex ].setXfId(26);
std::cout << "cellFormats[ " << nodeIndex << " ] summary: " << cellFormats[ nodeIndex ].summary() << std::endl;
nodeIndex = ( createAll ? cellStyles.create() : cellStyles.count() - 1 );
cellStyles[ nodeIndex ].setName( "test cellStyle" );
cellStyles[ nodeIndex ].setXfId( 77 );
cellStyles[ nodeIndex ].setBuiltinId( 7 );
cellStyles[ nodeIndex ].setOutlineStyle( 8 );
cellStyles[ nodeIndex ].setHidden( true );
cellStyles[ nodeIndex ].setCustomBuiltin( true );
std::cout << "cellStyles[ " << nodeIndex << " ] summary: " << cellStyles[ nodeIndex ].summary() << std::endl;
std::cout << " numberFormats.count() is " << numberFormats.count() << std::endl;
std::cout << " fonts.count() is " << fonts.count() << std::endl;
std::cout << " fills.count() is " << fills.count() << std::endl;
std::cout << " borders.count() is " << borders.count() << std::endl;
std::cout << "cellStyleFormats.count() is " << cellStyleFormats.count() << std::endl;
std::cout << " cellFormats.count() is " << cellFormats.count() << std::endl;
std::cout << " cellStyles.count() is " << cellStyles.count() << std::endl;
} // end if( testBasics )
XLStyleIndex mergedCellFormat = cellFormats.create( cellFormats[ wks.cell("E4").cellFormat() ] );
cellFormats[ mergedCellFormat ].alignment(XLCreateIfMissing).setHorizontal(XLAlignCenter);
cellFormats[ mergedCellFormat ].alignment(XLCreateIfMissing).setVertical(XLAlignTop);
cellFormats[ mergedCellFormat ].alignment(XLCreateIfMissing).setTextRotation(5);
cellFormats[ mergedCellFormat ].alignment(XLCreateIfMissing).setWrapText(true);
wks.cell("E4") = "merged red range #1\n - hidden cell values are intact!";
wks.mergeCells("E4:G7"); // merge cells without deletion of contents
// How to get the value of a merged range that a cell is a part of (by getting the top left cell first)
std::cout << "value of cell F6 is " << wks.cell("F6") << std::endl; // empty
XLMergeCells merges = wks.merges(); // get the worksheet's collection of merged ranges
int32_t mergeIndexForF6 = merges.findMergeByCell("F6"); // determine if F6 is contained within any merge
if( mergeIndexForF6 != -1 ) { // if cell is found at mergeIndexForF6
std::string mergeRef = merges[ mergeIndexForF6 ]; // get the actual merge reference
size_t pos = mergeRef.find_first_of(':'); //
XLCellReference topLeftRef(mergeRef.substr(0, pos)); // extract from the merge the top left cell
// output information about the merge
std::cout << "mergeIndexForF6 is " << mergeIndexForF6 << " , this merge reference is " << mergeRef << " and the top left cell is " << topLeftRef.address() << std::endl;
// output the value of the merge's top left cell
std::cout << "value of cell F6 by merge is \"" << wks.cell(topLeftRef) << "\"" << std::endl;
}
XLStyleIndex mergedCellFormatWithBorder = cellFormats.create( cellFormats[ mergedCellFormat ] );
if( false ) // enable this if you want to experiment with the borderFormat
cellFormats[ mergedCellFormatWithBorder ].setBorderIndex( borderFormat );
wks.cell("E4").setCellFormat( mergedCellFormatWithBorder );
wks.cell("J5") = "merged red range #2\n - hidden cell contents have been deleted!";
wks.mergeCells("J5:L8", XLEmptyHiddenCells); // merge cells with deletion of contents
wks.cell("J5").setCellFormat( mergedCellFormat );
// ===== BEGIN conditional formatting demo
{
XLDiffCellFormats & diffCellFormats = doc.styles().diffCellFormats(); // get a handle on differential cell formats
// Create some differential cell formats that can be used for conditional formatting
XLStyleIndex lowStyle = diffCellFormats.create();
XLStyleIndex justRightStyle = diffCellFormats.create();
XLStyleIndex highStyle = diffCellFormats.create();
XLColor gray( "dddddddd" );
XLColor orange( "00ffcc00" );
diffCellFormats[ lowStyle ].font().setFontColor( blue );
diffCellFormats[ lowStyle ].fill().setPatternType( XLPatternSolid );
diffCellFormats[ lowStyle ].fill().setColor( gray );
diffCellFormats[ lowStyle ].fill().setBackgroundColor( gray );
diffCellFormats[ justRightStyle ].font().setFontColor( green );
diffCellFormats[ justRightStyle ].fill().setPatternType( XLPatternNone );
// diffCellFormats[ justRightStyle ].fill().setColor( yellow );
diffCellFormats[ highStyle ].font().setFontColor( red );
diffCellFormats[ highStyle ].fill().setPatternType( XLPatternSolid );
diffCellFormats[ highStyle ].fill().setColor( orange );
// Now create some rules applying conditional formatting to a range
XLConditionalFormats fmts = wks.conditionalFormats();
size_t newFmtIndex = fmts.create(); // will be 0 for this demo
XLConditionalFormat fmt = fmts[ newFmtIndex ];
fmt.setSqref("B13:B19");
XLCfRules fmtRules = fmt.cfRules();
// make 3 cfRule entries
fmtRules.create();
fmtRules.create();
fmtRules.create();
fmtRules[ 0 ].setType( XLCfType::CellIs );
fmtRules[ 0 ].setOperator( XLCfOperator::LessThanOrEqual );
fmtRules[ 0 ].setFormula("4");
fmtRules[ 0 ].setDxfId(lowStyle);
fmtRules[ 1 ].setType( XLCfType::CellIs );
fmtRules[ 1 ].setOperator( XLCfOperator::Equal );
fmtRules[ 1 ].setFormula("5");
fmtRules[ 1 ].setDxfId(justRightStyle);
fmtRules[ 2 ].setType( XLCfType::CellIs );
fmtRules[ 2 ].setOperator( XLCfOperator::GreaterThanOrEqual );
fmtRules[ 2 ].setFormula("6");
fmtRules[ 2 ].setDxfId(highStyle);
// Manipulating rule priorities manually:
// priorities: 1, 2, 3
fmtRules.setPriority(1, 1); // 2, 1, 4 // "mess up" the sequence
fmtRules.setPriority(0, 1); // 1, 2, 5 // insert an existing priority at index 0
fmtRules.setPriority(2, 3); // 1, 2, 3 // re-assign the priority 3
fmtRules.setPriority(1, 1); // 2, 1, 4 // "mess up" the sequence
fmtRules.setPriority(2, 3); // 2, 1, 3 // re-assign the priority 3
fmtRules.setPriority(1, 4); // 2, 4, 3 // temp-assign priority 4 to index 1
fmtRules.setPriority(0, 1); // 1, 4, 3 // re-assign priority 1 to index 0
fmtRules.setPriority(1, 2); // 1, 2, 3 // re-assign priority 2 to index 1
fmtRules.setPriority(1, 1); // 2, 1, 4 // "mess up" the sequence
// renumber priorities while retaining the sequence:
fmtRules.renumberPriorities(10); // 20, 10, 30 // renumber priorities with higher increment
fmtRules.renumberPriorities(21845); // 21845, 43690, 65535 - max possible priority value used
// not allowed:
// fmtRules.create(); // triggers an error because no priority value can be assigned anymore
// fmtRules.renumberPriorities(21846); // triggers an error because 3*21846 exceeds uint16_t range
fmtRules.renumberPriorities(); // 2, 1, 3 // renumber priorities while retaining the sequence
std::cout << std::endl << "conditionalFormatting entries summary: " << wks.conditionalFormats().summary() << std::endl;
// Finally, set some exemplary values in the range
wks.cell("B12") = "conditional formatting example";
wks.cell("B12").setCellFormat( boldDefault );
int cellValue = 1;
for( XLCellAssignable c : wks.range("B13:B19") ) c = cellValue++;
}
// ===== END conditional formatting demo
doc.saveAs("./Demo10.xlsx", XLForceOverwrite);
doc.close();
return 0;
}