diff --git a/.gitignore b/.gitignore index 70584c44..7c4ab4c6 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ _temp.c examples/* !examples/*.c !examples/logo.png +!examples/logo_small.png !examples/Makefile cov-int libxlsxwriter-coverity.tgz diff --git a/docs/images/headers_footers.png b/docs/images/headers_footers.png index d6ad0490..00784176 100644 Binary files a/docs/images/headers_footers.png and b/docs/images/headers_footers.png differ diff --git a/examples/headers_footers.c b/examples/headers_footers.c index 768888e3..8f30887d 100644 --- a/examples/headers_footers.c +++ b/examples/headers_footers.c @@ -9,12 +9,14 @@ * &L Justification Left * &C Center * &R Right + * * &P Information Page number * &N Total number of pages * &D Date * &T Time * &F File name * &A Worksheet name + * * &fontsize Font Font size * &"font,style" Font name and style * &U Single underline @@ -22,8 +24,10 @@ * &S Strikethrough * &X Superscript * &Y Subscript + * * &[Picture] Images Image placeholder * &G Same as &[Picture] + * * && Miscellaneous Literal ampersand & * * Copyright 2014-2018, John McNamara, jmcnamara@cpan.org @@ -54,29 +58,25 @@ int main() { /* - * This is an example of some of the header/footer variables. + * A simple example to start */ - lxw_worksheet *worksheet2 = workbook_add_worksheet(workbook, "Variables"); - char header2[] = "&LPage &P of &N" "&CFilename: &F" "&RSheetname: &A"; - char footer2[] = "&LCurrent date: &D" "&RCurrent time: &T"; - lxw_row_t breaks[] = {20, 0}; + lxw_worksheet *worksheet2 = workbook_add_worksheet(workbook, "Image"); + lxw_header_footer_options header_options = {.image_left = "logo_small.png"}; - worksheet_set_header(worksheet2, header2); - worksheet_set_footer(worksheet2, footer2); + worksheet_set_header_opt(worksheet2, "&L&[Picture]", &header_options); + worksheet_set_margins(worksheet2, -1, -1, 1.3, -1); worksheet_set_column(worksheet2, 0, 0, 50, NULL); worksheet_write_string(worksheet2, 0, 0, preview, NULL); - worksheet_set_h_pagebreaks(worksheet2, breaks); - worksheet_write_string(worksheet2, 20, 0, "Next page", NULL); - /* - * This example shows how to use more than one font. + * This is an example of some of the header/footer variables. */ - lxw_worksheet *worksheet3 = workbook_add_worksheet(workbook, "Mixed fonts"); - char header3[] = "&C&\"Courier New,Bold\"Hello &\"Arial,Italic\"World"; - char footer3[] = "&C&\"Symbol\"e&\"Arial\" = mc&X2"; + lxw_worksheet *worksheet3 = workbook_add_worksheet(workbook, "Variables"); + char header3[] = "&LPage &P of &N" "&CFilename: &F" "&RSheetname: &A"; + char footer3[] = "&LCurrent date: &D" "&RCurrent time: &T"; + lxw_row_t breaks[] = {20, 0}; worksheet_set_header(worksheet3, header3); worksheet_set_footer(worksheet3, footer3); @@ -84,24 +84,29 @@ int main() { worksheet_set_column(worksheet3, 0, 0, 50, NULL); worksheet_write_string(worksheet3, 0, 0, preview, NULL); + worksheet_set_h_pagebreaks(worksheet3, breaks); + worksheet_write_string(worksheet3, 20, 0, "Next page", NULL); + /* - * Example of line wrapping. + * This example shows how to use more than one font. */ - lxw_worksheet *worksheet4 = workbook_add_worksheet(workbook, "Word wrap"); - char header4[] = "&CHeading 1\nHeading 2"; + lxw_worksheet *worksheet4 = workbook_add_worksheet(workbook, "Mixed fonts"); + char header4[] = "&C&\"Courier New,Bold\"Hello &\"Arial,Italic\"World"; + char footer4[] = "&C&\"Symbol\"e&\"Arial\" = mc&X2"; worksheet_set_header(worksheet4, header4); + worksheet_set_footer(worksheet4, footer4); worksheet_set_column(worksheet4, 0, 0, 50, NULL); worksheet_write_string(worksheet4, 0, 0, preview, NULL); /* - * Example of inserting a literal ampersand & + * Example of line wrapping. */ - lxw_worksheet *worksheet5 = workbook_add_worksheet(workbook, "Ampersand"); - char header5[] = "&CCuriouser && Curiouser - Attorneys at Law"; + lxw_worksheet *worksheet5 = workbook_add_worksheet(workbook, "Word wrap"); + char header5[] = "&CHeading 1\nHeading 2"; worksheet_set_header(worksheet5, header5); @@ -109,6 +114,18 @@ int main() { worksheet_write_string(worksheet5, 0, 0, preview, NULL); + /* + * Example of inserting a literal ampersand & + */ + lxw_worksheet *worksheet6 = workbook_add_worksheet(workbook, "Ampersand"); + char header6[] = "&CCuriouser && Curiouser - Attorneys at Law"; + + worksheet_set_header(worksheet6, header6); + + worksheet_set_column(worksheet6, 0, 0, 50, NULL); + worksheet_write_string(worksheet6, 0, 0, preview, NULL); + + workbook_close(workbook); return 0; diff --git a/examples/logo_small.png b/examples/logo_small.png new file mode 100644 index 00000000..779f4d34 Binary files /dev/null and b/examples/logo_small.png differ diff --git a/include/xlsxwriter/worksheet.h b/include/xlsxwriter/worksheet.h index fc393063..8361eb4b 100644 --- a/include/xlsxwriter/worksheet.h +++ b/include/xlsxwriter/worksheet.h @@ -875,16 +875,28 @@ typedef struct lxw_vml_obj { /** * @brief Header and footer options. * - * Optional parameters used in the worksheet_set_header_opt() and + * Optional parameters used in the `worksheet_set_header_opt()` and * worksheet_set_footer_opt() functions. * */ typedef struct lxw_header_footer_options { - /** Header or footer margin in inches. Excel default is 0.3. */ + /** Header or footer margin in inches. Excel default is 0.3. Must by + * larger than 0.0. See `worksheet_set_header_opt()`. */ double margin; + /** The left header image filename, with path if required. This should + * have a corresponding `&G/&[Picture]` placeholder in the `&L` section of + * the header/footer string. See `worksheet_set_header_opt()`. */ char *image_left; + + /** The center header image filename, with path if required. This should + * have a corresponding `&G/&[Picture]` placeholder in the `&C` section of + * the header/footer string. See `worksheet_set_header_opt()`. */ char *image_center; + + /** The right header image filename, with path if required. This should + * have a corresponding `&G/&[Picture]` placeholder in the `&R` section of + * the header/footer string. See `worksheet_set_header_opt()`. */ char *image_right; } lxw_header_footer_options; @@ -2989,7 +3001,11 @@ void worksheet_set_margins(lxw_worksheet *worksheet, double left, * | `&S` | | Strikethrough | * | `&X` | | Superscript | * | `&Y` | | Subscript | + * | `&[Picture]` | Images | Image placeholder | + * | `&G` | | Same as `&[Picture]` | + * | `&&` | Miscellaneous | Literal ampersand & | * + * Note: inserting images requires the `worksheet_set_header_opt()` function. * * Text in headers and footers can be justified (aligned) to the left, center * and right by prefixing the text with the control characters `&L`, `&C` and @@ -3113,17 +3129,14 @@ void worksheet_set_margins(lxw_worksheet *worksheet, double left, * @code * * $ unzip myfile.xlsm -d myfile - * $ xmllint --format `find myfile -name "*.xml" | xargs` | egrep "Header|Footer" + * $ xmllint --format `find myfile -name "*.xml" | xargs` | egrep "Header|Footer" | sed 's/&/\&/g' * * - * &L&P + * &L&P * * * @endcode * - * Note that in this case you need to unescape the Html. In the above example - * the header string would be `&L&P`. - * * To include a single literal ampersand `&` in a header or footer you should * use a double ampersand `&&`: * @@ -3131,8 +3144,8 @@ void worksheet_set_margins(lxw_worksheet *worksheet, double left, * worksheet_set_header(worksheet, "&CCuriouser && Curiouser - Attorneys at Law"); * @endcode * - * Note, the header or footer string must be less than 255 characters. Strings - * longer than this will not be written. + * Note, Excel requires that the header or footer string must be less than 255 + * characters. Strings longer than this will not be written. * */ lxw_error worksheet_set_header(lxw_worksheet *worksheet, const char *string); @@ -3159,19 +3172,43 @@ lxw_error worksheet_set_footer(lxw_worksheet *worksheet, const char *string); * * @return A #lxw_error code. * - * The syntax of this function is the same as worksheet_set_header() with an + * The syntax of this function is the same as `worksheet_set_header()` with an * additional parameter to specify options for the header. * - * Currently, the only available option is the header margin: + * The #lxw_header_footer_options options are: + * + * - `margin`: Header or footer margin in inches. The value must by larger + * than 0.0. The Excel default is 0.3. + * + * - `image_left`: The left header image filename, with path if required. This + * should have a corresponding `&G/&[Picture]` placeholder in the `&L` + * section of the header/footer string. + * + * - `image_center`: The center header image filename, with path if + * required. This should have a corresponding `&G/&[Picture]` placeholder in + * the `&C` section of the header/footer string. + * + * - `image_right`: The right header image filename, with path if + * required. This should have a corresponding `&G/&[Picture]` placeholder in + * the `&R` section of the header/footer string. * * @code + * lxw_header_footer_options header_options = { .margin = 0.2 }; * - * lxw_header_footer_options header_options = { 0.2 }; - * - * worksheet_set_header_opt(worksheet, "Some text", &header_options); - * + * worksheet_set_header_opt(worksheet, "Some text", &header_options); * @endcode * + * Images can be inserted in the header by specifying the `&[Picture]` + * placeholder and a filename/path to the image: + * + * @code + * lxw_header_footer_options header_options = {.image_left = "logo.png"}; + * + * worksheet_set_header_opt(worksheet, "&L&[Picture]", &header_options); + * @endcode + * + * @image html headers_footers.png + * */ lxw_error worksheet_set_header_opt(lxw_worksheet *worksheet, const char *string, @@ -3186,7 +3223,7 @@ lxw_error worksheet_set_header_opt(lxw_worksheet *worksheet, * * @return A #lxw_error code. * - * The syntax of this function is the same as worksheet_set_header_opt(). + * The syntax of this function is the same as `worksheet_set_header_opt()`. * */ lxw_error worksheet_set_footer_opt(lxw_worksheet *worksheet,