[GH-ISSUE #305] Header or footer string length #244

Closed
opened 2026-05-05 12:01:39 -06:00 by gitea-mirror · 2 comments
Owner

Originally created by @vic7tar on GitHub (Sep 8, 2020).
Original GitHub issue: https://github.com/jmcnamara/libxlsxwriter/issues/305

Originally assigned to: @jmcnamara on GitHub.

Hello.
Excel requires that the header or footer string must be less than 255 characters.
A simple example.
Running ActiveSheet.PageSetup.LeftHeader = String (253, "Ž") displays exactly 253 Unicode characters in the header, the maximum count including &L.
But to use the worksheet_set_header() function, I have to convert the string “&LŽ…253 times…Ž” to UTF-8 encoding. As a result, the input string for worksheet_set_header() will already be 508 ASCII characters long. As a result, the header and footer on the sheet of the generated book will not be displayed.

Originally created by @vic7tar on GitHub (Sep 8, 2020). Original GitHub issue: https://github.com/jmcnamara/libxlsxwriter/issues/305 Originally assigned to: @jmcnamara on GitHub. Hello. Excel requires that the header or footer string must be less than 255 characters. A simple example. Running **ActiveSheet.PageSetup.LeftHeader = String (253, "Ž")** displays exactly 253 Unicode characters in the header, the maximum count including &L. But to use the **worksheet_set_header()** function, I have to convert the string _“&LŽ…253 times…Ž”_ to UTF-8 encoding. As a result, the input string for **worksheet_set_header()** will already be 508 ASCII characters long. As a result, the header and footer on the sheet of the generated book will not be displayed.
gitea-mirror 2026-05-05 12:01:39 -06:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

@jmcnamara commented on GitHub (Sep 8, 2020):

Excel requires that the header or footer string must be less than 255 characters.

Correct and there are checks in the libxlsxwriter code for that. Although, there looks like there is a bug that restricts it to 254 characters, I need to check that.

Running ActiveSheet.PageSetup.LeftHeader = String (253, "Ž") displays exactly 253 Unicode characters in the header, the maximum count including &L.

Again, correct.

But to use the worksheet_set_header() function, I have to convert the string “&LŽ…253 times…Ž” to UTF-8 encoding. As a result, the input string for worksheet_set_header() will already be 508 ASCII characters long. As a result, the header and footer on the sheet of the generated book will not be displayed.

That isn't the case. If the source file is UTF-8 encoded then there will be only 255 characters in the file. The number of bytes required to make up the UTF-8 string doesn't matter.

However, there is a bug (thanks for pointing that out) in libxlsxwriter where it stores the string in a 255 byte fixed sized buffer.

I'll fix that with a dynamic buffer but in the meantime you can apply the following patch to master:

diff --git a/include/xlsxwriter/worksheet.h b/include/xlsxwriter/worksheet.h
index 456fbfc..9bcb465 100644
--- a/include/xlsxwriter/worksheet.h
+++ b/include/xlsxwriter/worksheet.h
@@ -59,7 +59,8 @@
 #define LXW_ROW_MAX                    1048576
 #define LXW_COL_MAX                    16384
 #define LXW_COL_META_MAX               128
-#define LXW_HEADER_FOOTER_MAX          255
+#define LXW_HEADER_FOOTER_MAX       255
+#define LXW_HEADER_FOOTER_BUFFER_SIZE (LXW_HEADER_FOOTER_MAX * 4) /* TODO. */
 #define LXW_MAX_NUMBER_URLS            65530
 #define LXW_PANE_NAME_LENGTH           12      /* bottomRight + 1 */
 #define LXW_IMAGE_BUFFER_SIZE          1024
@@ -1702,8 +1703,8 @@ typedef struct lxw_worksheet {
     uint8_t outline_col_level;

     uint8_t header_footer_changed;
-    char header[LXW_HEADER_FOOTER_MAX];
-    char footer[LXW_HEADER_FOOTER_MAX];
+    char header[LXW_HEADER_FOOTER_BUFFER_SIZE];
+    char footer[LXW_HEADER_FOOTER_BUFFER_SIZE];

     struct lxw_repeat_rows repeat_rows;
     struct lxw_repeat_cols repeat_cols;
diff --git a/src/worksheet.c b/src/worksheet.c
index 8c16659..2d66961 100644
--- a/src/worksheet.c
+++ b/src/worksheet.c
@@ -7937,7 +7937,7 @@ worksheet_set_header_opt(lxw_worksheet *self, const char *string,
     if (!string)
         return LXW_ERROR_NULL_PARAMETER_IGNORED;

-    if (lxw_utf8_strlen(string) >= LXW_HEADER_FOOTER_MAX)
+    if (lxw_utf8_strlen(string) > LXW_HEADER_FOOTER_MAX)
         return LXW_ERROR_255_STRING_LENGTH_EXCEEDED;

     lxw_strcpy(self->header, string);
@@ -8045,7 +8045,7 @@ worksheet_set_footer_opt(lxw_worksheet *self, const char *string,
     if (!string)
         return LXW_ERROR_NULL_PARAMETER_IGNORED;

-    if (lxw_utf8_strlen(string) >= LXW_HEADER_FOOTER_MAX)
+    if (lxw_utf8_strlen(string) > LXW_HEADER_FOOTER_MAX)
         return LXW_ERROR_255_STRING_LENGTH_EXCEEDED;

     lxw_strcpy(self->footer, string);

Then you can compile a program like this (where the source code is UTF-8 encoded):

#include "xlsxwriter.h"

int main() {

    lxw_workbook *workbook  = workbook_new("gh305.xlsx");

    lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
    char header[] = "&CŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽ";

    lxw_error error = worksheet_set_header(worksheet, header);

    if (error)
        printf("Error %d = %s\n", error, lxw_strerror(error));


    workbook_close(workbook);

    return 0;
}

Which gives the expected output:

screenshot

Thanks for the bug report. I'll add a test and fix this soon.

<!-- gh-comment-id:688813400 --> @jmcnamara commented on GitHub (Sep 8, 2020): > Excel requires that the header or footer string must be less than 255 characters. Correct and there are checks in the libxlsxwriter code for that. Although, there looks like there is a bug that restricts it to 254 characters, I need to check that. > Running ActiveSheet.PageSetup.LeftHeader = String (253, "Ž") displays exactly 253 Unicode characters in the header, the maximum count including &L. Again, correct. > But to use the **worksheet_set_header()** function, I have to convert the string _“&LŽ…253 times…Ž”_ to UTF-8 encoding. As a result, the input string for **worksheet_set_header()** will already be 508 ASCII characters long. As a result, the header and footer on the sheet of the generated book will not be displayed. That isn't the case. If the source file is UTF-8 encoded then there will be only 255 characters in the file. The number of bytes required to make up the UTF-8 string doesn't matter. **However**, there is a bug (thanks for pointing that out) in libxlsxwriter where it stores the string in a 255 byte fixed sized buffer. I'll fix that with a dynamic buffer but in the meantime you can apply the following patch to master: ```diff diff --git a/include/xlsxwriter/worksheet.h b/include/xlsxwriter/worksheet.h index 456fbfc..9bcb465 100644 --- a/include/xlsxwriter/worksheet.h +++ b/include/xlsxwriter/worksheet.h @@ -59,7 +59,8 @@ #define LXW_ROW_MAX 1048576 #define LXW_COL_MAX 16384 #define LXW_COL_META_MAX 128 -#define LXW_HEADER_FOOTER_MAX 255 +#define LXW_HEADER_FOOTER_MAX 255 +#define LXW_HEADER_FOOTER_BUFFER_SIZE (LXW_HEADER_FOOTER_MAX * 4) /* TODO. */ #define LXW_MAX_NUMBER_URLS 65530 #define LXW_PANE_NAME_LENGTH 12 /* bottomRight + 1 */ #define LXW_IMAGE_BUFFER_SIZE 1024 @@ -1702,8 +1703,8 @@ typedef struct lxw_worksheet { uint8_t outline_col_level; uint8_t header_footer_changed; - char header[LXW_HEADER_FOOTER_MAX]; - char footer[LXW_HEADER_FOOTER_MAX]; + char header[LXW_HEADER_FOOTER_BUFFER_SIZE]; + char footer[LXW_HEADER_FOOTER_BUFFER_SIZE]; struct lxw_repeat_rows repeat_rows; struct lxw_repeat_cols repeat_cols; diff --git a/src/worksheet.c b/src/worksheet.c index 8c16659..2d66961 100644 --- a/src/worksheet.c +++ b/src/worksheet.c @@ -7937,7 +7937,7 @@ worksheet_set_header_opt(lxw_worksheet *self, const char *string, if (!string) return LXW_ERROR_NULL_PARAMETER_IGNORED; - if (lxw_utf8_strlen(string) >= LXW_HEADER_FOOTER_MAX) + if (lxw_utf8_strlen(string) > LXW_HEADER_FOOTER_MAX) return LXW_ERROR_255_STRING_LENGTH_EXCEEDED; lxw_strcpy(self->header, string); @@ -8045,7 +8045,7 @@ worksheet_set_footer_opt(lxw_worksheet *self, const char *string, if (!string) return LXW_ERROR_NULL_PARAMETER_IGNORED; - if (lxw_utf8_strlen(string) >= LXW_HEADER_FOOTER_MAX) + if (lxw_utf8_strlen(string) > LXW_HEADER_FOOTER_MAX) return LXW_ERROR_255_STRING_LENGTH_EXCEEDED; lxw_strcpy(self->footer, string); ``` Then you can compile a program like this (where the source code is UTF-8 encoded): ```C #include "xlsxwriter.h" int main() { lxw_workbook *workbook = workbook_new("gh305.xlsx"); lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); char header[] = "&CŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽ"; lxw_error error = worksheet_set_header(worksheet, header); if (error) printf("Error %d = %s\n", error, lxw_strerror(error)); workbook_close(workbook); return 0; } ``` Which gives the expected output: ![screenshot](https://user-images.githubusercontent.com/94267/92472013-cb07d080-f1d0-11ea-9c5c-5d586c0a8318.png) Thanks for the bug report. I'll add a test and fix this soon.
Author
Owner

@jmcnamara commented on GitHub (Sep 8, 2020):

Fixed on master. Thanks for the report.

<!-- gh-comment-id:689026458 --> @jmcnamara commented on GitHub (Sep 8, 2020): Fixed on master. Thanks for the report.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github-starred/libxlsxwriter#244
No description provided.