gx
chenyc
2025-06-09 81ced3885266779c3a3813a0e4687962375b1d62
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import FileSaver from 'file-saver'
import * as XLSX from 'xlsx'
// 自动计算col列宽
function auto_width(ws, data) {
  /*set worksheet max width per col*/
  const colWidth = data.map(row => row.map(val => {
    /*if null/undefined*/
    if (val == null) {
      return { 'wch': 10 }
    }
    /*if chinese*/
    else if (val.toString().charCodeAt(0) > 255) {
      return { 'wch': val.toString().length * 2 }
    } else {
      return { 'wch': val.toString().length }
    }
  }))
  /*start in the first row*/
  let result = colWidth[0]
  for (let i = 1; i < colWidth.length; i++) {
    for (let j = 0; j < colWidth[i].length; j++) {
      if (result[j]['wch'] < colWidth[i][j]['wch']) {
        result[j]['wch'] = colWidth[i][j]['wch']
      }
    }
  }
  ws['!cols'] = result
}
// 将json数据转换成数组
function json_to_array(key, jsonData) {
  return jsonData.map(v => key.map(j => {
    return v[j]
  }))
}
/**
 * @param header Object,表头
 * @param data Array,表体数据
 * @param key Array,字段名
 * @param title String,标题(会居中显示),即excel表格第一行
 * @param filename String,文件名
 * @param autoWidth Boolean,是否自动根据key自定义列宽度
 */
export const exportJsonToExcel = ({
  header,
  data,
  key,
  title,
  filename,
  autoWidth
}) => {
  const wb = XLSX.utils.book_new()
  if (header) {
    data.unshift(header)
  }
  if (title) {
    data.unshift(title)
  }
  const ws = XLSX.utils.json_to_sheet(data, {
    header: key,
    skipHeader: true
  })
  // 合并单元格以覆盖整个第一行
  // ws['!merges'] = [{ s: {r:0, c:0}, e: {r:0, c:header.length - 1} }];
  if (autoWidth) {
    const arr = json_to_array(key, data)
    auto_width(ws, arr)
  }
  XLSX.utils.book_append_sheet(wb, ws, filename)
  XLSX.writeFile(wb, filename + '.xlsx')
}
 
/**
 * 自动计算并设置列宽
 * @param {Object} ws - 工作表对象
 * @param {Array} data - 表格数据(二维数组)
 */
function autoWidth(ws, data) {
  // 初始化每列宽度为默认值10
  const colWidths = Array(data[0].length).fill(10);
 
  // 遍历数据以计算最大宽度
  data.forEach(row => {
    row.forEach((val, index) => {
      let length = val ? (typeof val === 'string' ? getStrLen(val) : String(val).length) : 10;
      if (colWidths[index] < length) {
        colWidths[index] = length; // 更新最大宽度
      }else{
        colWidths[index] = 20; // 更新最大宽度
      }
    });
  });
 
  // 设置列宽
  ws['!cols'] = colWidths.map(width => ({ wch: width }));
}
/**
 * 计算字符串长度,考虑多字节字符(如中文)
 * @param {string} str - 输入字符串
 * @returns {number} 字符串长度
 */
function getStrLen(str) {
  return [...str].reduce((len, char) => len + (char.charCodeAt(0) > 255 ? 2 : 1), 0);
}
export const exportTableToExcel=(divId:string,name:string)=>{
  var wb = XLSX.utils.table_to_book(document.querySelector(divId));//关联dom节点
  console.log(wb)
  // 获取第一个工作表
  const ws = wb.Sheets[wb.SheetNames[0]];
  
  // 获取表格数据作为二维数组
  const data = XLSX.utils.sheet_to_json(ws, { header: 1 });
 
  // 设置列宽
  autoWidth(ws, data);
  var wbout = XLSX.write(wb, {
        bookType: 'xlsx',
        bookSST: true,
        type: 'array'
    })
  try {
        FileSaver.saveAs(new Blob([wbout], {
            type: 'application/octet-stream'
        }), `${name}.xlsx`)//自定义文件名
    } catch (e) {
        if (typeof console !== 'undefined') console.log(e, wbout);
    }
    return wbout
}
 
export const exportTableToExcel2 = async (divId: string, name: string): Promise<Uint8Array | null> => {
  try {
    // 关联 DOM 节点
    const tableElement = document.querySelector(divId);
    if (!tableElement) {
      console.error("Table element not found");
      return null;
    }
 
    // 转换表格为工作簿
    const wb = XLSX.utils.table_to_book(tableElement);
    console.log(wb);
 
    // 将工作簿写入文件
    const wbout = XLSX.write(wb, {
      bookType: 'xlsx',
      bookSST: true,
      type: 'array',
    });
 
    // 保存文件
    await new Promise<void>((resolve, reject) => {
      try {
        FileSaver.saveAs(
          new Blob([wbout], { type: 'application/octet-stream' }),
          `${name}.xlsx`
        );
        resolve();
      } catch (e) {
        console.error("Error saving file:", e);
        reject(e);
      }
    });
 
    // 返回生成的二进制数组
    return wbout;
  } catch (error) {
    console.error("Error exporting table to Excel:", error);
    return null;
  }
};
export default {
  exportJsonToExcel,
  exportTableToExcel
}