• vue:功能:table动态合并+前端导出


    场景:第一列WM 名字相同,行内合并,后面的列合并的行数根据第一列合并的行来。第二列‘累计请假天数'根据合并的几列显示数值。后续需合并的列以第一列合并行数为基准

    注)当前数据表头固定,行内数据不固定。以第一列WM为判断条件,相同名字的那几行数据合并单元格。合并相同名字的那几行数据,后面的列有需要和第一列合并条件一样。

    1、根据查询条件:日期。查询近三月日期数据。表头的日期是根据查询的日期条件的前三个月来。日期格式月份转换成英文格式。

    2、导出的数据和页面保持一致

    注)合并数据,后端提供的数据可能不是按照人在一起的顺序,前端需要处理下数据格式,把同一个人的放在一起

    注)本示例是用 vue3+element plus 实现的。

    效果图:

    一、完整代码实现

    1、页面代码

    1. <script lang="ts" setup>
    2. import dayjs from 'dayjs'
    3. import * as api from '@/api/trade/LeaveDay'
    4. import useConfig from '@/views/trade/LeavePay/hooks/useConfig'
    5. const { handleFilterMonth } = useConfig()
    6. import OutExcelSheet from '@/hooks/web/outToExcelManySheet'
    7. defineOptions({ name: 'LeaveDay' })
    8. const message = useMessage() // 消息弹窗
    9. const { t } = useI18n() // 国际化
    10. const loading = ref(true) // 列表的加载中
    11. const total = ref(0) // 列表的总页数
    12. const list = ref([]) // 列表的数据
    13. const queryParams = reactive({
    14. startDate: dayjs().subtract(1, 'month').format('YYYY-MM')
    15. })
    16. const queryFormRef = ref() // 搜索的表单
    17. /** 搜索按钮操作 */
    18. const handleQuery = () => {
    19. getList()
    20. }
    21. /** 重置按钮操作 */
    22. const resetQuery = () => {
    23. queryFormRef.value.resetFields()
    24. handleQuery()
    25. }
    26. /** 查询列表 */
    27. const getList = async () => {
    28. // mock 数据
    29. // loading.value = false
    30. // list.value = tableList.value
    31. // 列表数据
    32. loading.value = true
    33. try {
    34. // const data = await api.getLeavePayPage(queryParams)
    35. // mock数据
    36. const data = tableList.value
    37. // 1、TotalLeavePayOut 根据 同一个name 的 LeavePayOut 的总和
    38. const names = [...new Set(data.map((item) => item.name))]
    39. const updatedDemo = names.map((name) => {
    40. const list = data.filter((val) => val.name === name)
    41. const sum = list.reduce((accumulator, current) => {
    42. return accumulator + Number(current.leavePayout || 0)
    43. }, 0)
    44. return {
    45. name,
    46. list,
    47. sum: sum.toString()
    48. }
    49. })
    50. // console.log('updatedDemo', updatedDemo)
    51. // 2、导出表格时所需的合计值
    52. totalSum.value = updatedDemo.reduce((accumulator, item) => {
    53. if (item.sum) {
    54. return accumulator + parseFloat(item.sum)
    55. }
    56. return accumulator
    57. }, 0)
    58. console.log('累计值', totalSum.value)
    59. // 3、数据是没有按顺序来的,需处理成一个人的假期放在一起,方便合并数据
    60. const newList = updatedDemo.flatMap((item) => item.list)
    61. console.log(newList)
    62. // 3、合计的值放到每行对应的数据里
    63. const result = newList.map((item) => {
    64. const matchingItem = updatedDemo.find((val) => val.name === item.name)
    65. if (matchingItem) {
    66. item.totalLeavePayout = matchingItem.sum
    67. }
    68. return item
    69. })
    70. console.log('result', result)
    71. // 4、最终数据
    72. list.value = result
    73. } finally {
    74. loading.value = false
    75. }
    76. }
    77. // mock数据
    78. const tableList = ref([
    79. {
    80. name: 'karla',
    81. leaveDays: null,
    82. paidLeaveDate: '2023-01-01',
    83. actualDaysOneMonth: '10',
    84. actualDaysTwoMonth: '18',
    85. actualDaysThreeMonth: '18',
    86. payoutCommissionOneMonthPrice: '10000',
    87. payoutCommissionTwoMonthPrice: '20000',
    88. payoutCommissionThreeMonthPrice: '30000',
    89. averageCommission: '1400',
    90. commissionDuringLeave: '640',
    91. leavePayout: '760',
    92. totalLeavePayout: ''
    93. },
    94. {
    95. name: 'karla',
    96. leaveDays: null,
    97. paidLeaveDate: '2023-01-04',
    98. actualDaysOneMonth: '10',
    99. actualDaysTwoMonth: '18',
    100. actualDaysThreeMonth: '18',
    101. payoutCommissionOneMonthPrice: '10000',
    102. payoutCommissionTwoMonthPrice: '20000',
    103. payoutCommissionThreeMonthPrice: '30000',
    104. averageCommission: '1400',
    105. commissionDuringLeave: '1600',
    106. leavePayout: '0',
    107. totalLeavePayout: ''
    108. },
    109. {
    110. name: 'karla',
    111. leaveDays: null,
    112. paidLeaveDate: '2023-01-06',
    113. actualDaysOneMonth: '10',
    114. actualDaysTwoMonth: '18',
    115. actualDaysThreeMonth: '18',
    116. payoutCommissionOneMonthPrice: '10000',
    117. payoutCommissionTwoMonthPrice: '20000',
    118. payoutCommissionThreeMonthPrice: '30000',
    119. averageCommission: '1400',
    120. commissionDuringLeave: '1800',
    121. leavePayout: '0',
    122. totalLeavePayout: ''
    123. },
    124. {
    125. name: 'karla',
    126. leaveDays: null,
    127. paidLeaveDate: '2023-01-24',
    128. actualDaysOneMonth: '10',
    129. actualDaysTwoMonth: '18',
    130. actualDaysThreeMonth: '18',
    131. payoutCommissionOneMonthPrice: '10000',
    132. payoutCommissionTwoMonthPrice: '20000',
    133. payoutCommissionThreeMonthPrice: '30000',
    134. averageCommission: '1400',
    135. commissionDuringLeave: '',
    136. leavePayout: '0',
    137. totalLeavePayout: ''
    138. },
    139. {
    140. name: 'karla',
    141. leaveDays: null,
    142. paidLeaveDate: '2023-01-18',
    143. actualDaysOneMonth: '10',
    144. actualDaysTwoMonth: '18',
    145. actualDaysThreeMonth: '18',
    146. payoutCommissionOneMonthPrice: '10000',
    147. payoutCommissionTwoMonthPrice: '20000',
    148. payoutCommissionThreeMonthPrice: '30000',
    149. averageCommission: '1400',
    150. commissionDuringLeave: '1200',
    151. leavePayout: '200',
    152. totalLeavePayout: ''
    153. },
    154. {
    155. name: 'York',
    156. leaveDays: null,
    157. paidLeaveDate: '2023-01-18',
    158. actualDaysOneMonth: '28',
    159. actualDaysTwoMonth: '24',
    160. actualDaysThreeMonth: '18',
    161. payoutCommissionOneMonthPrice: '10000',
    162. payoutCommissionTwoMonthPrice: '20000',
    163. payoutCommissionThreeMonthPrice: '30000',
    164. averageCommission: '1500',
    165. commissionDuringLeave: '1800',
    166. leavePayout: '0',
    167. totalLeavePayout: ''
    168. },
    169. {
    170. name: 'York',
    171. leaveDays: null,
    172. paidLeaveDate: '2023-01-24',
    173. actualDaysOneMonth: '28',
    174. actualDaysTwoMonth: '24',
    175. actualDaysThreeMonth: '18',
    176. payoutCommissionOneMonthPrice: '10000',
    177. payoutCommissionTwoMonthPrice: '20000',
    178. payoutCommissionThreeMonthPrice: '30000',
    179. averageCommission: '1500',
    180. commissionDuringLeave: '700',
    181. leavePayout: '800',
    182. totalLeavePayout: ''
    183. },
    184. {
    185. name: 'Caleb',
    186. leaveDays: null,
    187. paidLeaveDate: '2023-01-29',
    188. actualDaysOneMonth: '22',
    189. actualDaysTwoMonth: '15',
    190. actualDaysThreeMonth: '17',
    191. payoutCommissionOneMonthPrice: '8899.12',
    192. payoutCommissionTwoMonthPrice: '7833',
    193. payoutCommissionThreeMonthPrice: '1455.63',
    194. averageCommission: '1366.8',
    195. commissionDuringLeave: '734.8',
    196. leavePayout: '632',
    197. totalLeavePayout: ''
    198. }
    199. ])
    200. const exportList = ref([
    201. [
    202. 'WM',
    203. 'Total Leave days',
    204. 'Paid Leave Date',
    205. 'Actual working days of previous 3 months\t(第一个月)',
    206. 'Actual working days of previous 3 months\t(第二个月)',
    207. 'Actual working days of previous 3 months\t(第三个月)',
    208. 'Payout of commission 3 months\t第一个月)',
    209. 'Payout of commission 3 months\t(第二个月)',
    210. 'Payout of commission 3 months\t(第三个月)',
    211. 'Average commission / day',
    212. 'Commission during leave',
    213. 'Leave Payout',
    214. 'Total Leave Payout'
    215. ],
    216. [
    217. 'karla',
    218. 5,
    219. '2023-01-01',
    220. '10',
    221. '18',
    222. '18',
    223. '10000',
    224. '20000',
    225. '30000',
    226. '1400',
    227. '640',
    228. '760',
    229. '0.00'
    230. ],
    231. [
    232. 'karla',
    233. 5,
    234. '2023-01-04',
    235. '10',
    236. '18',
    237. '18',
    238. '10000',
    239. '20000',
    240. '30000',
    241. '1400',
    242. '1600',
    243. '0.00',
    244. '0.00'
    245. ],
    246. [
    247. 'karla',
    248. 5,
    249. '2023-01-06',
    250. '10',
    251. '18',
    252. '18',
    253. '10000',
    254. '20000',
    255. '30000',
    256. '1400',
    257. '1800',
    258. '0.00',
    259. '0.00'
    260. ],
    261. [
    262. 'karla',
    263. 5,
    264. '2023-01-24',
    265. '10',
    266. '18',
    267. '18',
    268. '10000',
    269. '20000',
    270. '30000',
    271. '1400',
    272. '0.00',
    273. '0.00',
    274. '0.00'
    275. ],
    276. [
    277. 'karla',
    278. 5,
    279. '2023-01-18',
    280. '10',
    281. '18',
    282. '18',
    283. '10000',
    284. '20000',
    285. '30000',
    286. '1400',
    287. '1600',
    288. '0.00',
    289. '0.00'
    290. ],
    291. [
    292. 'York',
    293. 2,
    294. '2023-01-18',
    295. '28',
    296. '24',
    297. '18',
    298. '10000',
    299. '20000',
    300. '30000',
    301. '1500',
    302. '1800',
    303. '0.00',
    304. '666'
    305. ],
    306. [
    307. 'York',
    308. 2,
    309. '2023-01-24',
    310. '28',
    311. '24',
    312. '18',
    313. '10000',
    314. '20000',
    315. '30000',
    316. '1500',
    317. '700',
    318. '800',
    319. '666'
    320. ],
    321. [
    322. 'Caleb',
    323. 1,
    324. '2023-01-29',
    325. '22',
    326. '15',
    327. '17',
    328. '8899.12',
    329. '7833',
    330. '1455.63',
    331. '1366.8',
    332. '734.8',
    333. '632',
    334. '0.00'
    335. ]
    336. ])
    337. const saveRow = ref() // 存放的就是第一列中同name的合并
    338. const objectSpanMethod = ({ row, column, rowIndex, columnIndex }) => {
    339. // 第一列(WM)行合并
    340. if (columnIndex === 0) {
    341. // 1、取出tableList中每条数据的name,并去重
    342. const names = [...new Set(list.value.map((item) => item.name))]
    343. // 2、对表格数据按照name进行排序,并保持原始顺序
    344. const sortedData = names.reduce((acc, name) => {
    345. const matchingItems = list.value.filter((item) => item.name === name)
    346. return [...acc, ...matchingItems]
    347. }, [])
    348. // 3、匹配出names中的符合名字的第条数据的索引和最后一条索引。放在arr的数组里
    349. const arr = names.map((name) => {
    350. const firstIndex = sortedData.findIndex((item) => item.name === name)
    351. const lastIndex = sortedData.reduceRight((acc, item, index) => {
    352. if (item.name === name && acc === -1) {
    353. return index
    354. }
    355. return acc
    356. }, -1)
    357. return { firstNameIndex: firstIndex, lastNameIndex: lastIndex }
    358. })
    359. saveRow.value = arr
    360. // 4、把当列数据中相同的数据起始和结束的单元格进行合并
    361. const matchingData = arr.find(
    362. (item) => item.firstNameIndex <= rowIndex && rowIndex <= item.lastNameIndex
    363. )
    364. // 5、结果
    365. if (matchingData) {
    366. if (rowIndex === matchingData.firstNameIndex) {
    367. return {
    368. rowspan: matchingData.lastNameIndex - matchingData.firstNameIndex + 1,
    369. colspan: 1
    370. }
    371. } else {
    372. return {
    373. rowspan: 0,
    374. colspan: 0
    375. }
    376. }
    377. }
    378. }
    379. // 需合并列:根据第一列中需要合并的行数saveRow.value 来合并对应列下的行内合并
    380. if ([1, 3, 4, 5, 6, 7, 8, 12].includes(columnIndex)) {
    381. const matchingData = saveRow.value.find(
    382. (item) => item.firstNameIndex <= rowIndex && rowIndex <= item.lastNameIndex
    383. )
    384. if (matchingData) {
    385. if (rowIndex === matchingData.firstNameIndex) {
    386. const params = {
    387. rowspan: matchingData.lastNameIndex - matchingData.firstNameIndex + 1,
    388. colspan: 1,
    389. value: matchingData.lastNameIndex - matchingData.firstNameIndex + 1
    390. }
    391. list.value[rowIndex].leaveDays = params.value
    392. return params
    393. } else {
    394. return {
    395. rowspan: 0,
    396. colspan: 0
    397. }
    398. }
    399. }
    400. }
    401. }
    402. /** 导出 */
    403. const exportLoading = ref(false)
    404. const handleExport = async () => {
    405. try {
    406. // 导出的二次确认
    407. await message.exportConfirm()
    408. exportLoading.value = true
    409. const columnsHeader = {
    410. name: 'WM',
    411. leaveDays: 'Total Leave days',
    412. paidLeaveDate: 'Paid Leave Date',
    413. actualDaysOneMonth: handleFilterMonth(
    414. dayjs(queryParams.startDate).subtract(3, 'month').format('YYYY-MM')
    415. ),
    416. actualDaysTwoMonth: handleFilterMonth(
    417. dayjs(queryParams.startDate).subtract(2, 'month').format('YYYY-MM')
    418. ),
    419. actualDaysThreeMonth: handleFilterMonth(
    420. dayjs(queryParams.startDate).subtract(1, 'month').format('YYYY-MM')
    421. ),
    422. payoutCommissionOneMonthPrice: handleFilterMonth(
    423. dayjs(queryParams.startDate).subtract(3, 'month').format('YYYY-MM')
    424. ),
    425. payoutCommissionTwoMonthPrice: handleFilterMonth(
    426. dayjs(queryParams.startDate).subtract(2, 'month').format('YYYY-MM')
    427. ),
    428. payoutCommissionThreeMonthPrice: handleFilterMonth(
    429. dayjs(queryParams.startDate).subtract(1, 'month').format('YYYY-MM')
    430. ),
    431. averageCommission: 'Average commission/day',
    432. commissionDuringLeave: 'Commission during leave',
    433. leavePayout: 'Leave Payout',
    434. totalLeavePayout: 'Total Leave Payout'
    435. }
    436. const sheet1 = {
    437. name: 'LeavePay',
    438. data: [
    439. [
    440. 'WM',
    441. 'Total Leave days',
    442. 'Paid Leave Date',
    443. 'Actual working days of previous 3 months',
    444. '',
    445. '',
    446. 'Payout of commission 3 months',
    447. '',
    448. '',
    449. 'Average commission / day',
    450. 'Commission during leave',
    451. 'Leave Payout',
    452. 'Total Leave Payout'
    453. ],
    454. // ...exportList.value,
    455. ...OutExcelSheet.handleExcelTable(columnsHeader, list.value),
    456. ['', '', '', '', '', '', '', '', '', '', '', 'Total', '999']
    457. ],
    458. merges: [],
    459. rowHeights: [{ hpx: 20 }, { hpx: 20 }]
    460. }
    461. // 合并:第0列、第1列、第三列、第四列、第五列、第六列、第七列和第八列的相同值进行行合并
    462. const mergedRows = new Map()
    463. for (let i = 1; i < sheet1.data.length; i++) {
    464. const cellValue0 = sheet1.data[i][0]
    465. const cellValue1 = sheet1.data[i][1]
    466. const cellValue3 = sheet1.data[i][3]
    467. const cellValue4 = sheet1.data[i][4]
    468. const cellValue5 = sheet1.data[i][5]
    469. const cellValue6 = sheet1.data[i][6]
    470. const cellValue7 = sheet1.data[i][7]
    471. const cellValue8 = sheet1.data[i][8]
    472. const prevValue0 = sheet1.data[i - 1][0]
    473. const prevValue1 = sheet1.data[i - 1][1]
    474. const prevValue3 = sheet1.data[i - 1][3]
    475. const prevValue4 = sheet1.data[i - 1][4]
    476. const prevValue5 = sheet1.data[i - 1][5]
    477. const prevValue6 = sheet1.data[i - 1][6]
    478. const prevValue7 = sheet1.data[i - 1][7]
    479. const prevValue8 = sheet1.data[i - 1][8]
    480. if (
    481. cellValue0 === prevValue0 &&
    482. cellValue1 === prevValue1 &&
    483. cellValue3 === prevValue3 &&
    484. cellValue4 === prevValue4 &&
    485. cellValue5 === prevValue5 &&
    486. cellValue6 === prevValue6 &&
    487. cellValue7 === prevValue7 &&
    488. cellValue8 === prevValue8
    489. ) {
    490. if (mergedRows.has(cellValue0)) {
    491. // 更新合并的结束行索引
    492. mergedRows.get(cellValue0).end = i
    493. } else {
    494. // 添加新的合并信息
    495. mergedRows.set(cellValue0, { start: i - 1, end: i })
    496. }
    497. }
    498. }
    499. // 添加行合并信息到 mergesHeader
    500. for (const [value, { start, end }] of mergedRows.entries()) {
    501. sheet1.merges.push({ s: { r: start, c: 0 }, e: { r: end, c: 0 } })
    502. sheet1.merges.push({ s: { r: start, c: 1 }, e: { r: end, c: 1 } })
    503. sheet1.merges.push({ s: { r: start, c: 3 }, e: { r: end, c: 3 } })
    504. sheet1.merges.push({ s: { r: start, c: 4 }, e: { r: end, c: 4 } })
    505. sheet1.merges.push({ s: { r: start, c: 5 }, e: { r: end, c: 5 } })
    506. sheet1.merges.push({ s: { r: start, c: 6 }, e: { r: end, c: 6 } })
    507. sheet1.merges.push({ s: { r: start, c: 7 }, e: { r: end, c: 7 } })
    508. sheet1.merges.push({ s: { r: start, c: 8 }, e: { r: end, c: 8 } })
    509. sheet1.merges.push({ s: { r: start, c: 12 }, e: { r: end, c: 12 } })
    510. }
    511. const mergesHeader = [
    512. // 行合并
    513. { s: { r: 0, c: 3 }, e: { r: 0, c: 5 } },
    514. { s: { r: 0, c: 6 }, e: { r: 0, c: 8 } },
    515. // 列合并(r 表示行索引,c 表示列索引)
    516. { s: { r: 0, c: 0 }, e: { r: 1, c: 0 } }, // 第0列的第0行和第1行合并
    517. { s: { r: 0, c: 1 }, e: { r: 1, c: 1 } }, // 第1列的第0行和第1行合并
    518. { s: { r: 0, c: 2 }, e: { r: 1, c: 2 } }, // 第2列的第1行和第1行合并
    519. { s: { r: 0, c: 9 }, e: { r: 1, c: 9 } },
    520. { s: { r: 0, c: 10 }, e: { r: 1, c: 10 } },
    521. { s: { r: 0, c: 11 }, e: { r: 1, c: 11 } },
    522. { s: { r: 0, c: 12 }, e: { r: 1, c: 12 } }
    523. ]
    524. const sheetData = [sheet1]
    525. OutExcelSheet.exportSheetExcel(sheetData, mergesHeader, `LeavePay导出.xlsx`, true)
    526. } catch {
    527. } finally {
    528. exportLoading.value = false
    529. }
    530. }
    531. /** 初始化 **/
    532. onMounted(() => {
    533. getList()
    534. })
    535. script>

    2、封装的方法(导出)

    1. import XLSX from 'xlsx-js-style'
    2. import FileSaver from 'file-saver'
    3. export default {
    4. exportSheetExcel(sheetData, mergerArr, fileName = 'karlaExport.xlsx', statusBorder = false) {
    5. const wb = XLSX.utils.book_new() // 创建一个新工作簿
    6. for (let i = 0; i < sheetData.length; i++) {
    7. const sheet = sheetData[i]
    8. // 检查数据项是否存在
    9. if (!sheet.data) {
    10. continue // 如果数据项不存在,则跳过当前循环
    11. }
    12. const ws = XLSX.utils.aoa_to_sheet(sheet.data) // 将数据数组转换为工作表
    13. // 设置合并单元格
    14. ws['!merges'] =
    15. sheet.merges && sheet.merges.length > 0
    16. ? [...sheet.merges, ...(mergerArr || [])]
    17. : mergerArr
    18. // 设置列宽为自适应
    19. if (sheet.data.length > 0) {
    20. ws['!cols'] = sheet.data[0].map((_, index) => ({ wch: 15 }))
    21. }
    22. // 设置行高
    23. if (sheet.rowHeights && sheet.rowHeights.length > 0) {
    24. ws['!rows'] = sheet.rowHeights.map((height) => ({ hpt: height, hpx: height }))
    25. }
    26. const borderAll = {
    27. top: { style: 'thin' },
    28. bottom: { style: 'thin' },
    29. left: { style: 'thin' },
    30. right: { style: 'thin' }
    31. }
    32. // 设置单元格样式
    33. for (const key in ws) {
    34. if (ws.hasOwnProperty(key)) {
    35. const cell = ws[key]
    36. if (cell && typeof cell === 'object') {
    37. // 判断是否为最后一行【核心】
    38. const rowIndex = parseInt(key.replace(/[A-Z]/g, ''))
    39. if (statusBorder && rowIndex === sheet.data.length) {
    40. if (cell.s && cell.s.border) {
    41. delete cell.s.border.right // 删除右侧边框样式
    42. }
    43. // 内容居中
    44. cell.s = cell.s || {}
    45. cell.s.alignment = cell.s.alignment || {}
    46. cell.s.alignment.horizontal = 'center'
    47. cell.s.alignment.vertical = 'center'
    48. cell.s.alignment.wrapText = true
    49. } else {
    50. cell.s = {
    51. border: borderAll,
    52. alignment: {
    53. horizontal: 'center',
    54. vertical: 'center',
    55. wrapText: true
    56. },
    57. font: {
    58. sz: 12,
    59. color: {
    60. rgb: '000000'
    61. }
    62. },
    63. numFmt: 'General',
    64. fill: {
    65. fgColor: { rgb: 'FFFFFF' }
    66. }
    67. }
    68. }
    69. }
    70. }
    71. }
    72. XLSX.utils.book_append_sheet(wb, ws, sheet.name) // 将工作表添加到工作簿并指定名称
    73. }
    74. const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'array' }) // 将工作簿转换为数组
    75. const file = new Blob([wbout], { type: 'application/octet-stream' }) // 创建Blob对象
    76. FileSaver.saveAs(file, fileName) // 下载文件
    77. },
    78. // 二维数组中空的数据设置为 0【数据处理】
    79. emptyValues(array, defaultValue) {
    80. for (let i = 0; i < array.length; i++) {
    81. for (let j = 0; j < array[i].length; j++) {
    82. if (array[i][j] === null || array[i][j] === undefined || array[i][j] === '') {
    83. array[i][j] = defaultValue
    84. }
    85. }
    86. }
    87. return array
    88. },
    89. // 生成excel列表数据【格式转换】
    90. handleExcelTable(columnHeader, list) {
    91. if (list.length === 0) return []
    92. // 表头
    93. const tableColumn = Object.keys([columnHeader][0])
    94. // 表格生成的数据
    95. const sheet = [tableColumn]
    96. list.forEach((item) => {
    97. const row = tableColumn.map((column) => item[column])
    98. sheet.push(row)
    99. })
    100. // 表头匹配对应的中文
    101. const firstRow = sheet[0].map((column) => columnHeader[column])
    102. sheet[0] = firstRow
    103. return sheet || []
    104. }
    105. }

    3、处理方法代码

    1. import dayjs from 'dayjs'
    2. export default function useConfig() {
    3. const monthArray = [
    4. { month: '一月', abbreviation: 'Jan', number: '01' },
    5. { month: '二月', abbreviation: 'Feb', number: '02' },
    6. { month: '三月', abbreviation: 'Mar', number: '03' },
    7. { month: '四月', abbreviation: 'Apr', number: '04' },
    8. { month: '五月', abbreviation: 'May', number: '05' },
    9. { month: '六月', abbreviation: 'Jun', number: '06' },
    10. { month: '七月', abbreviation: 'Jul', number: '07' },
    11. { month: '八月', abbreviation: 'Aug', number: '08' },
    12. { month: '九月', abbreviation: 'Sep', number: '09' },
    13. { month: '十月', abbreviation: 'Oct', number: '10' },
    14. { month: '十一月', abbreviation: 'Nov', number: '11' },
    15. { month: '十二月', abbreviation: 'Dec', number: '12' }
    16. ]
    17. const handleFilterMonth = (val) => {
    18. const year = val.substring(0, 4)
    19. const month = val.substring(5, 7)
    20. const matchedData = monthArray.find((item) => month === item.number)?.abbreviation || month
    21. return `${year}-${matchedData}`
    22. }
    23. /** 获取两月之间的那个月 */
    24. const getMiddleMonth = (startDateStr, endDateStr) => {
    25. const startDate = dayjs(startDateStr).startOf('month')
    26. const endDate = dayjs(endDateStr).startOf('month')
    27. const middleMonth = startDate.add(1, 'month').format('YYYY-MM')
    28. return middleMonth
    29. }
    30. return {
    31. monthArray,
    32. handleFilterMonth,
    33. getMiddleMonth
    34. }
    35. }

  • 相关阅读:
    如何快速计算VRV空调需要添加冷媒的重量是多少
    第五十四周总结——WebRTC录制音频
    ensp由于win10 ARP表项未过期导致网络不通排查
    微信支付系统
    Spring IOC源码:ApplicationContext刷新前准备工作
    shell之常见网络命令介绍
    Promes 基于飞书的机器人告警推送
    JavaScript脚本操作CSS
    JavaScript大作业:基于HTML实现紫色化妆品包装设计公司企业网站
    如何使用 Disco 将黑白照片彩色化
  • 原文地址:https://blog.csdn.net/u013592575/article/details/136735196