Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5ea935f

Browse files
authored
fix: fix number format cell values ​​copied from excel with forced spaces (#5757)
1 parenta8b2717 commit5ea935f

File tree

3 files changed

+53
-2
lines changed

3 files changed

+53
-2
lines changed

‎packages/sheets-ui/src/services/clipboard/__tests__/clipboard-paste-form-excel.spec.ts‎

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
3131
import{SheetSkeletonManagerService}from'../../sheet-skeleton-manager.service';
3232
import{ISheetClipboardService}from'../clipboard.service';
3333
import{clipboardTestBed}from'./clipboard-test-bed';
34-
import{excelSample,excelSample2,excelSample3}from'./constant';
34+
import{excelSample,excelSample2,excelSample3,excelSample4}from'./constant';
3535

3636
describe('Test clipboard',()=>{
3737
letuniver:Univer;
@@ -353,5 +353,35 @@ describe('Test clipboard', () => {
353353
expect(cellValue?.v).toStrictEqual('123456789123456789');
354354
expect(cellValue?.t).toStrictEqual(CellValueType.FORCE_STRING);
355355
});
356+
357+
it('copy value is 1,234.57, the format "#,##0.00", the origin value 1234.567',async()=>{
358+
constworksheet=get(IUniverInstanceService).getUniverSheetInstance('test')?.getSheetBySheetId('sheet1');
359+
if(!worksheet)returnfalse;
360+
361+
// set selection to K1:L1
362+
constselectionManager=get(SheetsSelectionsService);
363+
selectionManager.addSelections([
364+
{
365+
range:{
366+
startRow:0,
367+
startColumn:0,
368+
endRow:0,
369+
endColumn:0,
370+
rangeType:RANGE_TYPE.NORMAL,
371+
},
372+
primary:null,
373+
style:null,
374+
},
375+
]);
376+
377+
// paste data, excelSample2 value is 000123456
378+
constres=awaitsheetClipboardService.legacyPaste(excelSample4);
379+
expect(res).toBeTruthy();
380+
381+
// check the values
382+
constcellValue=getValues(0,0,0,0)?.[0]?.[0];
383+
expect(cellValue?.v).toBe(1234.57);
384+
expect(cellValue?.t).toBe(CellValueType.NUMBER);
385+
});
356386
});
357387
});

‎packages/sheets-ui/src/services/clipboard/__tests__/constant.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ export const excelSample2 = '<html xmlns:o="urn:schemas-microsoft-com:office:off
2222
// copy value is 123456789123456789
2323
exportconstexcelSample3='<html xmlns:o="urn:schemas-microsoft-com:office:office"\r\nxmlns:x="urn:schemas-microsoft-com:office:excel"\r\nxmlns="http://www.w3.org/TR/REC-html40">\r\n\r\n<head>\r\n<meta http-equiv=Content-Type content="text/html; charset=utf-8">\r\n<meta name=ProgId content=Excel.Sheet>\r\n<meta name=Generator content="Microsoft Excel 15">\r\n<link id=Main-File rel=Main-File\r\nhref="file:///C:/Users/26775/AppData/Local/Temp/msohtmlclip1/01/clip.htm">\r\n<link rel=File-List\r\nhref="file:///C:/Users/26775/AppData/Local/Temp/msohtmlclip1/01/clip_filelist.xml">\r\n<style>\r\n\x3C!--table\r\n\t{mso-displayed-decimal-separator:"\\.";\r\n\tmso-displayed-thousand-separator:"\\,";}\r\n@page\r\n\t{margin:.75in .7in .75in .7in;\r\n\tmso-header-margin:.3in;\r\n\tmso-footer-margin:.3in;}\r\n.font5\r\n\t{color:windowtext;\r\n\tfont-size:9.0pt;\r\n\tfont-weight:400;\r\n\tfont-style:normal;\r\n\ttext-decoration:none;\r\n\tfont-family:等线;\r\n\tmso-generic-font-family:auto;\r\n\tmso-font-charset:134;}\r\ntr\r\n\t{mso-height-source:auto;\r\n\tmso-ruby-visibility:none;}\r\ncol\r\n\t{mso-width-source:auto;\r\n\tmso-ruby-visibility:none;}\r\nbr\r\n\t{mso-data-placement:same-cell;}\r\ntd\r\n\t{padding-top:1px;\r\n\tpadding-right:1px;\r\n\tpadding-left:1px;\r\n\tmso-ignore:padding;\r\n\tcolor:black;\r\n\tfont-size:11.0pt;\r\n\tfont-weight:400;\r\n\tfont-style:normal;\r\n\ttext-decoration:none;\r\n\tfont-family:等线;\r\n\tmso-generic-font-family:auto;\r\n\tmso-font-charset:134;\r\n\tmso-number-format:General;\r\n\ttext-align:general;\r\n\tvertical-align:middle;\r\n\tborder:none;\r\n\tmso-background-source:auto;\r\n\tmso-pattern:auto;\r\n\tmso-protection:locked visible;\r\n\twhite-space:nowrap;\r\n\tmso-rotate:0;}\r\n.xl65\r\n\t{mso-number-format:"\\@";}\r\nruby\r\n\t{ruby-align:left;}\r\nrt\r\n\t{color:windowtext;\r\n\tfont-size:9.0pt;\r\n\tfont-weight:400;\r\n\tfont-style:normal;\r\n\ttext-decoration:none;\r\n\tfont-family:等线;\r\n\tmso-generic-font-family:auto;\r\n\tmso-font-charset:134;\r\n\tmso-char-type:none;\r\n\tdisplay:none;}\r\n-->\r\n</style>\r\n</head>\r\n\r\n<body link="#0563C1" vlink="#954F72">\r\n\r\n<table border=0 cellpadding=0 cellspacing=0 width=115 style=\'border-collapse:\r\n collapse;width:86pt\'>\r\n <col width=115 style=\'mso-width-source:userset;mso-width-alt:3680;width:86pt\'>\r\n <tr height=19 style=\'height:14.25pt\'>\r\n\x3C!--StartFragment-->\r\n <td height=19 class=xl65 width=115 style=\'height:14.25pt;width:86pt\'>123456789123456789</td>\r\n\x3C!--EndFragment-->\r\n </tr>\r\n</table>\r\n\r\n</body>\r\n\r\n</html>\r\n';
2424

25+
// copy value is 1,234.57, the format "#,##0.00", the origin value 1234.567
26+
exportconstexcelSample4='<html xmlns:o="urn:schemas-microsoft-com:office:office"\r\nxmlns:x="urn:schemas-microsoft-com:office:excel"\r\nxmlns="http://www.w3.org/TR/REC-html40">\r\n\r\n<head>\r\n<meta http-equiv=Content-Type content="text/html; charset=utf-8">\r\n<meta name=ProgId content=Excel.Sheet>\r\n<meta name=Generator content="Microsoft Excel 15">\r\n<link id=Main-File rel=Main-File\r\nhref="file:///C:/Users/26775/AppData/Local/Temp/msohtmlclip1/01/clip.htm">\r\n<link rel=File-List\r\nhref="file:///C:/Users/26775/AppData/Local/Temp/msohtmlclip1/01/clip_filelist.xml">\r\n<style>\r\n\x3C!--table\r\n\t{mso-displayed-decimal-separator:"\\.";\r\n\tmso-displayed-thousand-separator:"\\,";}\r\n@page\r\n\t{margin:.75in .7in .75in .7in;\r\n\tmso-header-margin:.3in;\r\n\tmso-footer-margin:.3in;}\r\ntr\r\n\t{mso-height-source:auto;\r\n\tmso-ruby-visibility:none;}\r\ncol\r\n\t{mso-width-source:auto;\r\n\tmso-ruby-visibility:none;}\r\nbr\r\n\t{mso-data-placement:same-cell;}\r\ntd\r\n\t{padding-top:1px;\r\n\tpadding-right:1px;\r\n\tpadding-left:1px;\r\n\tmso-ignore:padding;\r\n\tcolor:black;\r\n\tfont-size:11.0pt;\r\n\tfont-weight:400;\r\n\tfont-style:normal;\r\n\ttext-decoration:none;\r\n\tfont-family:等线;\r\n\tmso-generic-font-family:auto;\r\n\tmso-font-charset:134;\r\n\tmso-number-format:General;\r\n\ttext-align:general;\r\n\tvertical-align:bottom;\r\n\tborder:none;\r\n\tmso-background-source:auto;\r\n\tmso-pattern:auto;\r\n\tmso-protection:locked visible;\r\n\twhite-space:nowrap;\r\n\tmso-rotate:0;}\r\n.xl65\r\n\t{mso-number-format:"_ * \\#\\,\\#\\#0\\.00_ \\;_ * \\\\-\\#\\,\\#\\#0\\.00_ \\;_ * \\0022-\\0022??_ \\;_ \\@_ ";}\r\nruby\r\n\t{ruby-align:left;}\r\nrt\r\n\t{color:windowtext;\r\n\tfont-size:9.0pt;\r\n\tfont-weight:400;\r\n\tfont-style:normal;\r\n\ttext-decoration:none;\r\n\tfont-family:等线;\r\n\tmso-generic-font-family:auto;\r\n\tmso-font-charset:134;\r\n\tmso-char-type:none;\r\n\tdisplay:none;}\r\n-->\r\n</style>\r\n</head>\r\n\r\n<body link="#0563C1" vlink="#954F72">\r\n\r\n<table border=0 cellpadding=0 cellspacing=0 width=122 style=\'border-collapse:\r\n collapse;width:92pt\'>\r\n <col width=122 style=\'mso-width-source:userset;mso-width-alt:3904;width:92pt\'>\r\n <tr height=34 style=\'height:25.5pt\'>\r\n\x3C!--StartFragment-->\r\n <td height=34 class=xl65 width=122 style=\'height:25.5pt;width:92pt\'><span\r\n style=\'mso-spacerun:yes\'>              </span>1,234.57 </td>\r\n\x3C!--EndFragment-->\r\n </tr>\r\n</table>\r\n\r\n</body>\r\n\r\n</html>\r\n';
27+
2528
exportconstgoogleSample='<google-sheets-html-origin><style type="text/css">\x3C!--td {border: 1px solid #cccccc;}br {mso-data-placement:same-cell;}--></style><table xmlns="http://www.w3.org/1999/xhtml" cellspacing="0" cellpadding="0" dir="ltr" border="1" style="table-layout:fixed;font-size:10pt;font-family:Arial;width:0px;border-collapse:collapse;border:none" data-sheets-root="1"><colgroup><col width="100"/><col width="100"/><col width="100"/><col width="100"/></colgroup><tbody><tr style="height:21px;"><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td></tr><tr style="height:21px;"><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;font-weight:bold;font-style:italic;" data-sheets-value="{&quot;1&quot;:2,&quot;2&quot;:&quot;Univer&quot;}">Univer</td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;background-color:#ff0000;" data-sheets-value="{&quot;1&quot;:2,&quot;2&quot;:&quot;univer&quot;}" data-sheets-textstyleruns="{&quot;1&quot;:0}{&quot;1&quot;:1,&quot;2&quot;:{&quot;2&quot;:{&quot;1&quot;:2,&quot;2&quot;:14275305},&quot;4&quot;:18,&quot;5&quot;:1,&quot;6&quot;:1}}{&quot;1&quot;:4}"><span style="font-size:10pt;font-family:Arial;font-style:normal;">u</span><span style="font-size:18pt;font-family:Arial;font-weight:bold;font-style:italic;color:#d9d2e9;">niv</span><span style="font-size:10pt;font-family:Arial;font-style:normal;">er</span></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td></tr><tr style="height:21px;"><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="border-bottom:1px solid #000000;overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="border-bottom:1px solid #000000;overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td></tr><tr style="height:21px;"><td style="border-right:1px solid #000000;overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="border-right:1px solid #000000;border-bottom:1px solid #000000;overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;text-align:center;" rowspan="1" colspan="2" data-sheets-value="{&quot;1&quot;:2,&quot;2&quot;:&quot;univer&quot;}">univer</td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td></tr><tr style="height:21px;"><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="border-bottom:1px solid #000000;overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="border-bottom:1px solid #000000;overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td></tr><tr style="height:21px;"><td style="border-right:1px solid #000000;overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="border-right:1px solid #000000;border-bottom:1px solid #000000;overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;text-align:center;" rowspan="2" colspan="2" data-sheets-value="{&quot;1&quot;:2,&quot;2&quot;:&quot;univer&quot;}"><span><div style="max-height:42px">univer</div></span></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td></tr><tr style="height:21px;"><td style="border-right:1px solid #000000;overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td></tr><tr style="height:21px;"><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="border-bottom:1px solid #000000;overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td></tr><tr style="height:21px;"><td style="border-right:1px solid #000000;overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="border-right:1px solid #000000;border-bottom:1px solid #000000;overflow:hidden;padding:2px 3px 2px 3px;vertical-align:middle;background-color:#ff0000;text-align:center;" rowspan="4" colspan="1" data-sheets-value="{&quot;1&quot;:2,&quot;2&quot;:&quot;univer&quot;}"><span><div style="max-height:84px">univer</div></span></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td></tr><tr style="height:21px;"><td style="border-right:1px solid #000000;overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td></tr><tr style="height:21px;"><td style="border-right:1px solid #000000;overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td></tr><tr style="height:21px;"><td style="border-right:1px solid #000000;overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td></tr><tr style="height:21px;"><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td></tr><tr style="height:21px;"><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;text-align:right;" data-sheets-value="{&quot;1&quot;:3,&quot;3&quot;:45607}" data-sheets-numberformat="{&quot;1&quot;:5,&quot;2&quot;:&quot;yyyy/m/d&quot;,&quot;3&quot;:1}">2024/11/11</td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td></tr><tr style="height:21px;"><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;"></td></tr></tbody></table>';
2629

2730
// font

‎packages/sheets-ui/src/services/clipboard/html-to-usm/converter.ts‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import type {
2727
IUniverSheetCopyDataModel,
2828
}from'../type';
2929
importtype{IAfterProcessRule,IPastePlugin}from'./paste-plugins/type';
30-
import{CustomRangeType,DEFAULT_WORKSHEET_ROW_HEIGHT,generateRandomId,ObjectMatrix,skipParseTagNames}from'@univerjs/core';
30+
import{CustomRangeType,DEFAULT_WORKSHEET_ROW_HEIGHT,generateRandomId,numfmt,ObjectMatrix,skipParseTagNames}from'@univerjs/core';
3131
import{handleStringToStyle,textTrim}from'@univerjs/ui';
3232
import{extractNodeStyle}from'./parse-node-style';
3333
importparseToDom,{convertToCellStyle,generateParagraphs}from'./utils';
@@ -467,6 +467,24 @@ export class HtmlToUSMService {
467467
}
468468

469469
private_getCellTextAndRichText(cell:Element,styleStr:string,skeleton?:SpreadsheetSkeleton){
470+
/**
471+
* mso-spacerun:yes is used to force spaces in html copied from excel.
472+
* if the remaining text is a number or parse to a number, return the remaining text directly.
473+
* e.g. excel cell value is 1234.567, and cell format is "#,##0.00", then the copied html is:
474+
* "<span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>1,234.57 "
475+
*/
476+
if(cell.innerHTML.includes('mso-spacerun:yes')){
477+
constcellText=cell.innerHTML.replace(/<span[^>]*mso-spacerun:yes[^>]*>.*?<\/span>/gi,'');
478+
constparseInfo=numfmt.parseNumber(cellText);
479+
480+
if(parseInfo&&parseInfo.v!==undefined&&parseInfo.v!==null){
481+
return{
482+
cellText,
483+
cellRichStyle:undefined,
484+
};
485+
}
486+
}
487+
470488
letcellText='';
471489
letcellRichStyle;
472490
constisRichText=/<[^>]+>/.test(cell.innerHTML);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp