2017-09-17 16:33:36 -05:00
|
|
|
//
|
2020-08-23 14:15:53 +00:00
|
|
|
// Copyright 2020 FoxyUtils ehf. All rights reserved.
|
|
|
|
//
|
|
|
|
// This is a commercial product and requires a license to operate.
|
|
|
|
// A trial license can be obtained at https://unidoc.io
|
|
|
|
//
|
|
|
|
// DO NOT EDIT: generated by unitwist Go source code obfuscator.
|
|
|
|
//
|
|
|
|
// Use of this source code is governed by the UniDoc End User License Agreement
|
|
|
|
// terms that can be accessed at https://unidoc.io/eula/
|
2017-09-17 16:33:36 -05:00
|
|
|
|
2020-08-23 14:15:53 +00:00
|
|
|
// Package format provides support for parsing and evaluating
|
|
|
|
// spreadsheetml/Excel number formats.
|
|
|
|
//
|
|
|
|
// Internally spreadsheets store numbers and dates values as a text
|
|
|
|
// representation of a floating point number (e.g. 1.2345). This number is then
|
|
|
|
// displayed in Excel or another spreadsheet viewer differently depending on the
|
|
|
|
// number fornat of the cell style applied to the cell.
|
|
|
|
//
|
|
|
|
// As an example, the same value of 1.2345 can be displayed as:
|
|
|
|
// - "1" with format "0"
|
|
|
|
// - "1.2" with format "0.0"
|
|
|
|
// - "1.23" with format "0.00"
|
|
|
|
// - "1.235" with format "0.000"
|
|
|
|
// - "123%" with format "0%"
|
|
|
|
// - "1 23/100" with fornat "0 0/100"
|
|
|
|
// - "1.23E+00" with format "0.00E+00"
|
|
|
|
// - "29:37:41s" with format `[h]:mm:ss"s"`
|
2022-12-06 11:56:49 +00:00
|
|
|
package format ;import (_cb "bytes";_g "fmt";_ca "github.com/unidoc/unioffice/common/logger";_d "io";_ce "math";_ge "strconv";_a "strings";_cd "time";);
|
2022-02-05 13:05:36 +00:00
|
|
|
|
|
|
|
// AddToken adds a format token to the format.
|
2022-12-06 11:56:49 +00:00
|
|
|
func (_dg *Format )AddToken (t FmtType ,l []byte ){if _dg ._eb {_dg ._eb =false ;return ;};switch t {case FmtTypeDecimal :_dg ._db =true ;case FmtTypeUnderscore :_dg ._eb =true ;case FmtTypeText :_dg .Whole =append (_dg .Whole ,Token {Type :t });case FmtTypeDate ,FmtTypeTime :_dg .Whole =append (_dg .Whole ,Token {Type :t ,DateTime :string (l )});case FmtTypePercent :_dg ._gc =true ;t =FmtTypeLiteral ;l =[]byte {'%'};fallthrough;case FmtTypeDigitOpt :fallthrough;case FmtTypeLiteral ,FmtTypeDigit ,FmtTypeDollar ,FmtTypeComma :if l ==nil {l =[]byte {0};};for _ ,_bb :=range l {if _dg .IsExponential {_dg .Exponent =append (_dg .Exponent ,Token {Type :t ,Literal :_bb });}else if !_dg ._db {_dg .Whole =append (_dg .Whole ,Token {Type :t ,Literal :_bb });}else {_dg .Fractional =append (_dg .Fractional ,Token {Type :t ,Literal :_bb });};};case FmtTypeDigitOptThousands :_dg ._gfg =true ;case FmtTypeFraction :_cc :=_a .Split (string (l ),"\u002f");if len (_cc )==2{_dg ._aa =true ;_dg ._gcg ,_ =_ge .ParseInt (_cc [1],10,64);for _ ,_dbe :=range _cc [1]{if _dbe =='?'||_dbe =='0'{_dg ._gdd ++;};};};default:_ca .Log .Debug ("\u0075\u006e\u0073u\u0070\u0070\u006f\u0072t\u0065\u0064\u0020\u0070\u0068\u0020\u0074y\u0070\u0065\u0020\u0069\u006e\u0020\u0070\u0061\u0072\u0073\u0065\u0020\u0025\u0076",t );};};func (_bea *Lexer )nextFmt (){_bea ._ffa =append (_bea ._ffa ,_bea ._cbg );_bea ._cbg =Format {}};var _gf =[...]uint8 {0,14,26,41,53,67,81,94,118,135,146,157,172,183};const _acfe int =34;func _ea (_ecd int64 )int64 {if _ecd < 0{return -_ecd ;};return _ecd ;};type Lexer struct{_cbg Format ;_ffa []Format ;};func (_gecc *Lexer )Lex (r _d .Reader ){_ffd ,_bgd ,_caa :=0,0,0;_aea :=-1;_ccff ,_ebcd ,_cegc :=0,0,0;_ =_ebcd ;_ =_cegc ;_bcef :=1;_ =_bcef ;_bgf :=make ([]byte ,4096);_bfa :=false ;for !_bfa {_ffb :=0;if _ccff > 0{_ffb =_bgd -_ccff ;};_bgd =0;_ceb ,_ecef :=r .Read (_bgf [_ffb :]);if _ceb ==0||_ecef !=nil {_bfa =true ;};_caa =_ceb +_ffb ;if _caa < len (_bgf ){_aea =_caa ;};{_ffd =_cce ;_ccff =0;_ebcd =0;_cegc =0;};{if _bgd ==_caa {goto _ccge ;};switch _ffd {case 34:goto _fbfa ;case 35:goto _ced ;case 0:goto _cfbe ;case 36:goto _ecca ;case 37:goto _afd ;case 1:goto _fdc ;case 2:goto _edg ;case 38:goto _cda ;case 3:goto _bebb ;case 4:goto _aed ;case 39:goto _dfda ;case 5:goto _ggg ;case 6:goto _cafc ;case 7:goto _ebf ;case 8:goto _acb ;case 40:goto _ggbd ;case 9:goto _caef ;case 41:goto _abcb ;case 10:goto _effb ;case 42:goto _gffc ;case 11:goto _dbc ;case 43:goto _aebd ;case 44:goto _aaf ;case 45:goto _ecf ;case 12:goto _daba ;case 46:goto _bcc ;case 13:goto _gfgc ;case 14:goto _dgf ;case 15:goto _cffe ;case 16:goto _addc ;case 47:goto _fcg ;case 17:goto _aef ;case 48:goto _abb ;case 18:goto _affd ;case 19:goto _cafb ;case 20:goto _dge ;case 49:goto _aedd ;case 50:goto _adef ;case 21:goto _fga ;case 22:goto _eggf ;case 23:goto _gdcb ;case 24:goto _gca ;case 25:goto _ddge ;case 51:goto _eaeg ;case 26:goto _feaf ;case 52:goto _gada ;case 53:goto _bab ;case 54:goto _egcc ;case 55:goto _fbde ;case 56:goto _ffab ;case 57:goto _abaa ;case 27:goto _cag ;case 28:goto _cbdb ;case 29:goto _cgg ;case 30:goto _afdf ;case 31:goto _aad ;case 58:goto _aged ;case 32:goto _aacb ;case 59:goto _befd ;case 33:goto _dgbg ;case 60:goto _daa ;case 61:goto _fca ;case 62:goto _ffbe ;};goto _abfb ;_cebg :switch _cegc {case 2:{_bgd =(_ebcd )-1;_gecc ._cbg .AddToken (FmtTypeDigit ,nil );};case 3:{_bgd =(_ebcd )-1;_gecc ._cbg .AddToken (FmtTypeDigitOpt ,nil );};case 5:{_bgd =(_ebcd )-1;};case 8:{_bgd =(_ebcd )-1;_gecc ._cbg .AddToken (FmtTypePercent ,nil );};case 13:{_bgd =(_ebcd )-1;_gecc ._cbg .AddToken (FmtTypeFraction ,_bgf [_ccff :_ebcd ]);};case 14:{_bgd =(_ebcd )-1;_gecc ._cbg .AddToken (FmtTypeDate ,_bgf [_ccff :_ebcd ]);};case 15:{_bgd =(_ebcd )-1;_gecc ._cbg .AddToken (FmtTypeTime ,_bgf [_ccff :_ebcd ]);};case 16:{_bgd =(_ebcd )-1;_gecc ._cbg .AddToken (FmtTypeTime ,_bgf [_ccff :_ebcd ]);};case 18:{_bgd =(_ebcd )-1;};case 20:{_bgd =(_ebcd )-1;_gecc ._cbg .AddToken (FmtTypeLiteral ,_bgf [_ccff :_ebcd ]);};case 21:{_bgd =(_ebcd )-1;_gecc ._cbg .AddToken (
|
2022-09-02 11:46:53 +00:00
|
|
|
|
|
|
|
// NumberGeneric formats the number with the generic format which attemps to
|
|
|
|
// mimic Excel's general formatting.
|
2022-12-06 11:56:49 +00:00
|
|
|
func NumberGeneric (v float64 )string {if _ce .Abs (v )>=_ac ||_ce .Abs (v )<=_b &&v !=0{return _adb (v );};_fbd :=make ([]byte ,0,15);_fbd =_ge .AppendFloat (_fbd ,v ,'f',-1,64);if len (_fbd )> 11{_fbc :=_fbd [11]-'0';if _fbc >=5&&_fbc <=9{_fbd [10]++;_fbd =_fbd [0:11];_fbd =_ebc (_fbd );};_fbd =_fbd [0:11];}else if len (_fbd )==11{if _fbd [len (_fbd )-1]=='9'{_fbd [len (_fbd )-1]++;_fbd =_ebc (_fbd );};};_fbd =_bge (_fbd );return string (_fbd );};func _ebc (_gfgg []byte )[]byte {for _ecc :=len (_gfgg )-1;_ecc > 0;_ecc --{if _gfgg [_ecc ]=='9'+1{_gfgg [_ecc ]='0';if _gfgg [_ecc -1]=='.'{_ecc --;};_gfgg [_ecc -1]++;};};if _gfgg [0]=='9'+1{_gfgg [0]='0';copy (_gfgg [1:],_gfgg [0:]);_gfgg [0]='1';};return _gfgg ;};const _cbd int =0;const _dcfd int =0;func _ede (_dfb _cd .Time ,_bca float64 ,_aac string )[]byte {_ega :=[]byte {};_fgd :=0;for _efb :=0;_efb < len (_aac );_efb ++{var _acf string ;if _aac [_efb ]==':'{_acf =string (_aac [_fgd :_efb ]);_fgd =_efb +1;}else if _efb ==len (_aac )-1{_acf =string (_aac [_fgd :_efb +1]);}else {continue ;};switch _acf {case "\u0064":_ega =_dfb .AppendFormat (_ega ,"\u0032");case "\u0068":_ega =_dfb .AppendFormat (_ega ,"\u0033");case "\u0068\u0068":_ega =_dfb .AppendFormat (_ega ,"\u0031\u0035");case "\u006d":_ega =_dfb .AppendFormat (_ega ,"\u0034");case "\u006d\u006d":_ega =_dfb .AppendFormat (_ega ,"\u0030\u0034");case "\u0073":_ega =_dfb .Round (_cd .Second ).AppendFormat (_ega ,"\u0035");case "\u0073\u002e\u0030":_ega =_dfb .Round (_cd .Second /10).AppendFormat (_ega ,"\u0035\u002e\u0030");case "\u0073\u002e\u0030\u0030":_ega =_dfb .Round (_cd .Second /100).AppendFormat (_ega ,"\u0035\u002e\u0030\u0030");case "\u0073\u002e\u00300\u0030":_ega =_dfb .Round (_cd .Second /1000).AppendFormat (_ega ,"\u0035\u002e\u00300\u0030");case "\u0073\u0073":_ega =_dfb .Round (_cd .Second ).AppendFormat (_ega ,"\u0030\u0035");case "\u0073\u0073\u002e\u0030":_ega =_dfb .Round (_cd .Second /10).AppendFormat (_ega ,"\u0030\u0035\u002e\u0030");case "\u0073\u0073\u002e0\u0030":_ega =_dfb .Round (_cd .Second /100).AppendFormat (_ega ,"\u0030\u0035\u002e0\u0030");case "\u0073\u0073\u002e\u0030\u0030\u0030":_ega =_dfb .Round (_cd .Second /1000).AppendFormat (_ega ,"\u0030\u0035\u002e\u0030\u0030\u0030");case "\u0041\u004d\u002fP\u004d":_ega =_dfb .AppendFormat (_ega ,"\u0050\u004d");case "\u005b\u0068\u005d":_ega =_ge .AppendInt (_ega ,int64 (_bca *24),10);case "\u005b\u006d\u005d":_ega =_ge .AppendInt (_ega ,int64 (_bca *24*60),10);case "\u005b\u0073\u005d":_ega =_ge .AppendInt (_ega ,int64 (_bca *24*60*60),10);case "":default:_ca .Log .Debug ("\u0075\u006e\u0073\u0075\u0070\u0070\u006f\u0072\u0074\u0065\u0064 \u0074\u0069\u006d\u0065\u0020\u0066\u006f\u0072\u006d\u0061t\u0020\u0025\u0073",_acf );};if _aac [_efb ]==':'{_ega =append (_ega ,':');};};return _ega ;};
|
2021-11-10 11:45:21 +00:00
|
|
|
|
2022-12-06 11:56:49 +00:00
|
|
|
// Format is a parsed number format.
|
|
|
|
type Format struct{Whole []Token ;Fractional []Token ;Exponent []Token ;IsExponential bool ;_aa bool ;_gc bool ;_caf bool ;_gfg bool ;_eb bool ;_db bool ;_gcg int64 ;_gdd int ;};func (_gd FmtType )String ()string {if _gd >=FmtType (len (_gf )-1){return _g .Sprintf ("F\u006d\u0074\u0054\u0079\u0070\u0065\u0028\u0025\u0064\u0029",_gd );};return _e [_gf [_gd ]:_gf [_gd +1]];};
|
|
|
|
|
|
|
|
// Number is used to format a number with a format string. If the format
|
|
|
|
// string is empty, then General number formatting is used which attempts to mimic
|
|
|
|
// Excel's general formatting.
|
|
|
|
func Number (v float64 ,f string )string {if f ==""||f =="\u0047e\u006e\u0065\u0072\u0061\u006c"||f =="\u0040"{return NumberGeneric (v );};_gb :=Parse (f );if len (_gb )==1{return _af (v ,_gb [0],false );}else if len (_gb )> 1&&v < 0{return _af (v ,_gb [1],true );}else if len (_gb )> 2&&v ==0{return _af (v ,_gb [2],false );};return _af (v ,_gb [0],false );};const _b =1e-10;func Parse (s string )[]Format {_afg :=Lexer {};_afg .Lex (_a .NewReader (s ));_afg ._ffa =append (_afg ._ffa ,_afg ._cbg );return _afg ._ffa ;};
|
2022-09-02 11:46:53 +00:00
|
|
|
|
|
|
|
// Token is a format token in the Excel format string.
|
2022-12-06 11:56:49 +00:00
|
|
|
type Token struct{Type FmtType ;Literal byte ;DateTime string ;};const _aff int =-1;func _af (_bbd float64 ,_cgf Format ,_fbfe bool )string {if _cgf ._caf {return NumberGeneric (_bbd );};_ef :=make ([]byte ,0,20);_fdd :=_ce .Signbit (_bbd );_ecg :=_ce .Abs (_bbd );_ccb :=int64 (0);_efa :=int64 (0);if _cgf .IsExponential {for _ecg >=10{_efa ++;_ecg /=10;};for _ecg < 1{_efa --;_ecg *=10;};}else if _cgf ._gc {_ecg *=100;}else if _cgf ._aa {if _cgf ._gcg ==0{_aca :=_ce .Pow (10,float64 (_cgf ._gdd ));_dc ,_ff :=1.0,1.0;_ =_dc ;for _bf :=1.0;_bf < _aca ;_bf ++{_ ,_da :=_ce .Modf (_ecg *float64 (_bf ));if _da < _ff {_ff =_da ;_dc =_bf ;if _da ==0{break ;};};};_cgf ._gcg =int64 (_dc );};_ccb =int64 (_ecg *float64 (_cgf ._gcg )+0.5);if len (_cgf .Whole )> 0&&_ccb > _cgf ._gcg {_ccb =int64 (_ecg *float64 (_cgf ._gcg ))%_cgf ._gcg ;_ecg -=float64 (_ccb )/float64 (_cgf ._gcg );}else {_ecg -=float64 (_ccb )/float64 (_cgf ._gcg );if _ce .Abs (_ecg )< 1{_cdg :=true ;for _ ,_bdee :=range _cgf .Whole {if _bdee .Type ==FmtTypeDigitOpt {continue ;};if _bdee .Type ==FmtTypeLiteral &&_bdee .Literal ==' '{continue ;};_cdg =false ;};if _cdg {_cgf .Whole =nil ;};};};};_bg :=1;for _ ,_ab :=range _cgf .Fractional {if _ab .Type ==FmtTypeDigit ||_ab .Type ==FmtTypeDigitOpt {_bg ++;};};_ecg +=5*_ce .Pow10 (-_bg );_dab ,_cef :=_ce .Modf (_ecg );_ef =append (_ef ,_gcc (_dab ,_bbd ,_cgf )...);_ef =append (_ef ,_aga (_cef ,_bbd ,_cgf )...);_ef =append (_ef ,_gccc (_efa ,_cgf )...);if _cgf ._aa {_ef =_ge .AppendInt (_ef ,_ccb ,10);_ef =append (_ef ,'/');_ef =_ge .AppendInt (_ef ,_cgf ._gcg ,10);};if !_fbfe &&_fdd {return "\u002d"+string (_ef );};return string (_ef );};const _e ="\u0046\u006d\u0074\u0054\u0079\u0070\u0065\u004c\u0069\u0074\u0065\u0072a\u006c\u0046\u006d\u0074\u0054\u0079\u0070\u0065\u0044\u0069\u0067\u0069\u0074\u0046\u006d\u0074\u0054y\u0070\u0065\u0044i\u0067\u0069\u0074\u004f\u0070\u0074\u0046\u006d\u0074\u0054\u0079\u0070\u0065\u0043o\u006d\u006d\u0061\u0046\u006d\u0074\u0054\u0079\u0070\u0065\u0044\u0065\u0063\u0069\u006da\u006c\u0046\u006d\u0074\u0054\u0079\u0070\u0065Pe\u0072\u0063e\u006e\u0074\u0046\u006d\u0074\u0054\u0079\u0070e\u0044\u006f\u006c\u006c\u0061\u0072\u0046\u006d\u0074Ty\u0070\u0065\u0044i\u0067\u0069\u0074\u004f\u0070\u0074\u0054\u0068\u006f\u0075\u0073\u0061n\u0064\u0073\u0046\u006d\u0074\u0054\u0079\u0070\u0065\u0055n\u0064\u0065\u0072\u0073c\u006f\u0072\u0065\u0046\u006d\u0074T\u0079\u0070\u0065\u0044\u0061\u0074\u0065\u0046\u006d\u0074\u0054y\u0070e\u0054\u0069\u006d\u0065\u0046\u006d\u0074\u0054\u0079\u0070\u0065\u0046\u0072\u0061\u0063t\u0069\u006f\u006e\u0046\u006dt\u0054\u0079\u0070\u0065\u0054e\u0078\u0074";
|
2022-04-09 14:27:46 +00:00
|
|
|
|
|
|
|
// FmtType is the type of a format token.
|
|
|
|
//go:generate stringer -type=FmtType
|
2022-12-06 11:56:49 +00:00
|
|
|
type FmtType byte ;
|
|
|
|
|
|
|
|
// Value formats a value as a number or string depending on if it appears to be
|
|
|
|
// a number or string.
|
|
|
|
func Value (v string ,f string )string {if IsNumber (v ){_bd ,_ :=_ge .ParseFloat (v ,64);return Number (_bd ,f );};return String (v ,f );};func _ec (_agg []byte )[]byte {for _dbg :=0;_dbg < len (_agg )/2;_dbg ++{_fbf :=len (_agg )-1-_dbg ;_agg [_dbg ],_agg [_fbf ]=_agg [_fbf ],_agg [_dbg ];};return _agg ;};const _fcf int =34;func _eaf (_aagc _cd .Time )_cd .Time {_aagc =_aagc .UTC ();return _cd .Date (_aagc .Year (),_aagc .Month (),_aagc .Day (),_aagc .Hour (),_aagc .Minute (),_aagc .Second (),_aagc .Nanosecond (),_cd .Local );};const _bdeee int =0;
|
|
|
|
|
|
|
|
// String returns the string formatted according to the type. In format strings
|
|
|
|
// this is the fourth item, where '@' is used as a placeholder for text.
|
|
|
|
func String (v string ,f string )string {_eg :=Parse (f );var _f Format ;if len (_eg )==1{_f =_eg [0];}else if len (_eg )==4{_f =_eg [3];};_cae :=false ;for _ ,_fd :=range _f .Whole {if _fd .Type ==FmtTypeText {_cae =true ;};};if !_cae {return v ;};_ag :=_cb .Buffer {};for _ ,_ccc :=range _f .Whole {switch _ccc .Type {case FmtTypeLiteral :_ag .WriteByte (_ccc .Literal );case FmtTypeText :_ag .WriteString (v );};};return _ag .String ();};
|