Skip to content

Feat configure headers and footers #863

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jun 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ To be clear, all contributions added to this library will be included in the lib
<li><a href="#worksheet-state">Worksheet State</a></li>
<li><a href="#worksheet-properties">Worksheet Properties</a></li>
<li><a href="#page-setup">Page Setup</a></li>
<li><a href="#header-footer">Header Footer</a></li>
<li>
<a href="#worksheet-views">Worksheet Views</a>
<ul>
Expand Down Expand Up @@ -374,6 +375,64 @@ worksheet.pageSetup.printTitlesColumn = 'A:C';
| Double Japan Postcard Rotated | 82 |
| 16K 197x273 mm | 119 |

## Header Footer
Here's how to add headers and footers. The added content is mainly text, such as time, introduction, file information, etc., and you can set the style of the text. In addition, you can set different texts for the first page and even page.

Warring: Not support add image

```javascript
// Set footer (default centered), result: "Page 2 of 16"
worksheet.headerFooter.oddFooter = "Page &P of &N";

// Set the footer (default centered) to bold, resulting in: "Page 2 of 16"
worksheet.headerFooter.oddFooter = "Page &P of &N";

// Set the left footer to 18px and italicize. Result: "Page 2 of 16"
worksheet.headerFooter.oddFooter = "&LPage &P of &N";

// Set the middle header to gray Aril, the result: "52 exceljs"
worksheet.headerFooter.oddHeader = "&C&KCCCCCC&\"Aril\"52 exceljs";

// Set the left, center, and right text of the footer. Result: “Exceljs” in the footer left. “demo.xlsx” in the footer center. “Page 2” in the footer right
worksheet.headerFooter.oddFooter = "&Lexceljs&C&F&RPage &P";

// Add different header & footer for the first page
worksheet.headerFooter.differentFirst = true;
worksheet.headerFooter.firstHeader = "Hello Exceljs";
worksheet.headerFooter.firstFooter = "Hello World"
```
**Supported headerFooter settings**
| Name | Default | Description |
| ----------------- | --------- | ----------- |
|differentFirst|false| Set the value of differentFirst as true, which indicates that headers/footers for first page are different from the other pages|
|differentOddEven|false|Set the value of differentOddEven as true, which indicates that headers/footers for odd and even pages are different|
|oddHeader|null|Set header string for odd(default) pages, could format the string|
|oddFooter|null|Set footer string for odd(default) pages, could format the string|
|evenHeader|null|Set header string for even pages, could format the string|
|evenFooter|null|Set footer string for even pages, could format the string|
|firstHeader|null|Set header string for the first page, could format the string|
|firstFooter|null|Set footer string for the first page, could format the string|

**Script Commands**
| Commands | Description |
| ----------------- | ----------- |
|&L|Set position to the left|
|&C|Set position to the center|
|&R|Set position to the right|
|&P|The current page number|
|&N|The total number of pages|
|&D|The current date|
|&T|The current time|
|&G|A picture|
|&A|The worksheet name|
|&F|The file name|
|&B|Make text bold|
|&I|Italicize text|
|&U|Underline text|
|&"font name"|font name, for example &"Aril"|
|&font size|font size, for example 12|
|&KHEXCode|font color, for example &KCCCCCC|

## Worksheet Views

Worksheets now support a list of views, that control how Excel presents the sheet:
Expand Down
66 changes: 63 additions & 3 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ npm install exceljs
<li><a href="#worksheet-state">工作表状态</a></li>
<li><a href="#worksheet-properties">工作表属性</a></li>
<li><a href="#page-setup">页面设置</a></li>
<li><a href="#header-footer">页眉和页脚</a></li>
<li>
<a href="#worksheet-views">工作表视图</a>
<ul>
Expand Down Expand Up @@ -360,6 +361,65 @@ worksheet.pageSetup.printTitlesColumn = 'A:C';
| 日本双明信片旋转 | 82 |
| 16K 197x273 mm | 119 |

## 页眉和页脚{#header-footer}
这里将介绍如何添加页眉和页脚,添加的内容主要是文本,比如时间,简介,文件信息等,并且可以设置文本的风格。此外,也可以针对首页,奇偶页设置不同的文本。

警告:不支持添加图片

```javascript
// 代码中出现的&开头字符对应变量,相关信息可查阅下文的变量表
// 设置页脚(默认居中),结果:“第 2 页,共 16 页”
worksheet.headerFooter.oddFooter = "第 &P 页,共 &N 页";

// 设置页脚(默认居中)加粗,结果:“第 2 页,共 16 页”
worksheet.headerFooter.oddFooter = "&B第 &P 页,共 &N 页";

// 设置左边页脚为18px大小并倾斜,结果:“第 2 页,共 16 页”
worksheet.headerFooter.oddFooter = "&L&18&I第 &P 页,共 &N 页";

// 设置中间页眉为灰色微软雅黑,结果:“52 exceljs”
worksheet.headerFooter.oddHeader = "&C&KCCCCCC&\"微软雅黑\"52 exceljs";

// 设置页脚的左中右文本,结果:页脚左“exceljs” 页脚中“demo.xlsx” 页脚右“第 2 页”
worksheet.headerFooter.oddFooter = "&Lexceljs&C&F&R第 &P 页";

// 为首页设置独特的内容
worksheet.headerFooter.differentFirst = true;
worksheet.headerFooter.firstHeader = "Hello Exceljs";
worksheet.headerFooter.firstFooter = "Hello World"
```
**属性表**
| 名称 | 默认值 | 描述 |
| ----------------- | --------- | ----------- |
|differentFirst|false|开启或关闭首页使用独特的文本内容|
|differentOddEven|false|开启或关闭奇数页和偶数页使用不同的文本内容|
|oddHeader|null|奇数页的页眉内容,如果 differentOddEven = false ,那么该项作为页面默认的页眉内容|
|oddFooter|null|奇数页的页脚内容,如果 differentOddEven = false ,那么该项作为页面默认的页脚内容|
|evenHeader|null|偶数页的页眉内容,differentOddEven = true 后有效|
|evenFooter|null|偶数页的页脚内容,differentOddEven = true 后有效|
|firstHeader|null|首页的页眉内容,differentFirst = true 后有效|
|firstFooter|null|首页的页脚内容,differentFirst = true 后有效|

**变量表**
| 名称 | 描述 |
| ----------------- | ----------- |
|&L|设置位置为左边|
|&C|设置位置为中间|
|&R|设置位置为右边|
|&P|当前页数|
|&N|总页数|
|&D|当前日期|
|&T|当前时间|
|&G|图片|
|&A|工作表名|
|&F|文件名|
|&B|文本加粗|
|&I|文本倾斜|
|&U|文本下划线|
|&"字体名称"|字体名称,比如:&“微软雅黑”|
|&数字|字体大小,比如12px大的文本:&12 |
|&KHEXCode|字体颜色,比如灰色:&KCCCCCC|

## 工作表视图{#worksheet-views}

工作表现在支持一个视图列表,用于控制Excel如何显示工作表:
Expand Down Expand Up @@ -865,7 +925,7 @@ ws.getRow(2).font = { name: 'Comic Sans MS', family: 4, size: 16, underline: 'do
此行为旨在通过减少创建的JS对象的数量来确定性能的优先级。
如果希望样式对象是独立的,则需要在分配它们之前克隆它们。
此外,默认情况下,如果从文件(或流)读取文档(如果电子表格实体共享相似的样式),则它们也将引用相同的样式对象。

### 数字格式{#number-formats}

```javascript
Expand Down Expand Up @@ -1491,7 +1551,7 @@ CSV解析器使用[fast-csv](https://www.npmjs.com/package/fast-csv)编写CS
这将把XLSX工作簿的内容存储在内存中。
这个StreamBuf对象可以通过属性workbook.stream访问,也可以用于
通过stream.read()直接访问字节或将内容传递给另一个流。

```javascript
// construct a streaming XLSX workbook writer with styles and shared strings
var options = {
Expand Down Expand Up @@ -1542,7 +1602,7 @@ worksheet.commit();

要完成XLSX文档,必须提交工作簿。如果未提交工作簿中的任何工作表,
它们将作为工作簿提交的一部分自动提交。

```javascript
// Finished the workbook.
workbook.commit()
Expand Down
85 changes: 63 additions & 22 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ export interface Font {
bold: boolean;
italic: boolean;
underline: boolean | 'none' | 'single' | 'double' | 'singleAccounting' | 'doubleAccounting';
vertAlign: 'superscript' | 'subscript';
vertAlign: 'superscript' | 'subscript';
strike: boolean;
outline: boolean;
}
Expand Down Expand Up @@ -341,7 +341,7 @@ export interface CellFormulaValue {
export interface CellSharedFormulaValue {
sharedFormula: string;
readonly formula?: string;
result?: number | string | Date| { error: CellErrorValue };
result?: number | string | Date | { error: CellErrorValue };
date1904: boolean;
}

Expand Down Expand Up @@ -771,6 +771,41 @@ export interface PageSetup {
printTitlesColumn: string;
}

export interface HeaderFooter {
/**
* Set the value of differentFirst as true, which indicates that headers/footers for first page are different from the other pages, `false` by default
*/
differentFirst: boolean,
/**
* Set the value of differentOddEven as true, which indicates that headers/footers for odd and even pages are different, `false` by default
*/
differentOddEven: boolean,
/**
* Set header string for odd pages, could format the string and `null` by default
*/
oddHeader: string,
/**
* Set footer string for odd pages, could format the string and `null` by default
*/
oddFooter: string,
/**
* Set header string for even pages, could format the string and `null` by default
*/
evenHeader: string,
/**
* Set footer string for even pages, could format the string and `null` by default
*/
evenFooter: string,
/**
* Set header string for the first page, could format the string and `null` by default
*/
firstHeader: string,
/**
* Set footer string for the first page, could format the string and `null` by default
*/
firstFooter: string
}

export type AutoFilter = string | {
from: string | { row: number; column: number };
to: string | { row: number; column: number };
Expand All @@ -783,26 +818,26 @@ export interface Image {
buffer?: Buffer;
}
export interface IAnchor {
col: number;
row: number;
nativeCol: number;
nativeRow: number;
nativeColOff: number;
nativeRowOff: number;
}
export class Anchor implements IAnchor{
col: number;
nativeCol: number;
nativeColOff: number;
nativeRow: number;
nativeRowOff: number;
row: number;

private readonly colWidth: number;
private readonly rowHeight: number;
worksheet: Worksheet;

constructor(model?: IAnchor|object);
col: number;
row: number;
nativeCol: number;
nativeRow: number;
nativeColOff: number;
nativeRowOff: number;
}
export class Anchor implements IAnchor {
col: number;
nativeCol: number;
nativeColOff: number;
nativeRow: number;
nativeRowOff: number;
row: number;

private readonly colWidth: number;
private readonly rowHeight: number;
worksheet: Worksheet;

constructor(model?: IAnchor | object);
}
export interface ImageRange {
tl: { col: number; row: number } | Anchor;
Expand Down Expand Up @@ -874,6 +909,7 @@ export interface WorksheetModel {
// dataValidations: this.dataValidations.model,
properties: WorksheetProperties;
pageSetup: Partial<PageSetup>;
headerFooter: HeaderFooter;
rowBreaks: RowBreak[];
views: WorksheetView[];
autoFilter: AutoFilter;
Expand All @@ -893,6 +929,11 @@ export interface Worksheet {
*/
pageSetup: Partial<PageSetup>;

/**
* Worksheet Header and Footer
*/
headerFooter: HeaderFooter;

/**
* Worksheet State
*/
Expand Down
23 changes: 18 additions & 5 deletions lib/doc/worksheet.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class Worksheet {
this.pageSetup = Object.assign(
{},
{
margins: { left: 0.7, right: 0.7, top: 0.75, bottom: 0.75, header: 0.3, footer: 0.3 },
margins: {left: 0.7, right: 0.7, top: 0.75, bottom: 0.75, header: 0.3, footer: 0.3},
orientation: 'portrait',
horizontalDpi: 4294967295,
verticalDpi: 4294967295,
Expand All @@ -89,6 +89,17 @@ class Worksheet {
options.pageSetup
);

this.headerFooter = {
differentFirst: false,
differentOddEven: false,
oddHeader: null,
oddFooter: null,
evenHeader: null,
evenFooter: null,
firstHeader: null,
firstFooter: null,
};

this.dataValidations = new DataValidations();

// for freezepanes, split, zoom, gridlines, etc
Expand Down Expand Up @@ -248,7 +259,7 @@ class Worksheet {
const counts = [];
let count = 0;
this.eachRow(row => {
row.eachCell(({ col }) => {
row.eachCell(({col}) => {
if (!counts[col]) {
counts[col] = true;
count++;
Expand Down Expand Up @@ -342,7 +353,7 @@ class Worksheet {
rDst.values = rSrc.values;
rDst.style = rSrc.style;
// eslint-disable-next-line no-loop-func
rSrc.eachCell({ includeEmpty: true }, (cell, colNumber) => {
rSrc.eachCell({includeEmpty: true}, (cell, colNumber) => {
rDst.getCell(colNumber).style = cell.style;
});
this._rows[i - 1] = undefined;
Expand All @@ -359,7 +370,7 @@ class Worksheet {
rDst.values = rSrc.values;
rDst.style = rSrc.style;
// eslint-disable-next-line no-loop-func
rSrc.eachCell({ includeEmpty: true }, (cell, colNumber) => {
rSrc.eachCell({includeEmpty: true}, (cell, colNumber) => {
rDst.getCell(colNumber).style = cell.style;
});
} else {
Expand Down Expand Up @@ -502,7 +513,7 @@ class Worksheet {
fillFormula(range, formula, results) {
// Define formula for top-left cell and share to rest
const decoded = colCache.decode(range);
const { top, left, bottom, right } = decoded;
const {top, left, bottom, right} = decoded;
const width = right - left + 1;
const masterAddress = colCache.encodeAddress(top, left);

Expand Down Expand Up @@ -591,6 +602,7 @@ class Worksheet {
properties: this.properties,
state: this.state,
pageSetup: this.pageSetup,
headerFooter: this.headerFooter,
rowBreaks: this.rowBreaks,
views: this.views,
autoFilter: this.autoFilter,
Expand Down Expand Up @@ -647,6 +659,7 @@ class Worksheet {
this.dataValidations = new DataValidations(value.dataValidations);
this.properties = value.properties;
this.pageSetup = value.pageSetup;
this.headerFooter = value.headerFooter;
this.views = value.views;
this.autoFilter = value.autoFilter;
this._media = value.media.map(medium => new Image(this, medium));
Expand Down
Loading