@borgar/fx 4.4.0 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fx.d.ts +6 -0
- package/dist/fx.js +1 -1
- package/docs/API.md +16 -14
- package/lib/a1.js +18 -9
- package/lib/constants.js +2 -2
- package/lib/lexer-srefs.spec.js +5 -0
- package/lib/lexerParts.js +24 -12
- package/lib/parseRef.spec.js +22 -11
- package/lib/parser.spec.js +90 -39
- package/lib/rc.js +4 -2
- package/lib/sr.spec.js +7 -0
- package/lib/translate-toA1.spec.js +5 -1
- package/lib/translate-toRC.spec.js +4 -1
- package/lib/translate.js +8 -5
- package/lib/translate.spec.js +21 -0
- package/package.json +6 -6
package/dist/fx.d.ts
CHANGED
|
@@ -552,12 +552,15 @@ export declare function tokenize(formula: string, options?: {
|
|
|
552
552
|
* @param formula A string (an Excel formula) or a token list that should be adjusted.
|
|
553
553
|
* @param anchorCell A simple string reference to an A1 cell ID (`AF123` or`$C$5`).
|
|
554
554
|
* @param [options={}] The options
|
|
555
|
+
* @param [options.allowTernary=true] Enables the recognition of ternary ranges in the style of `A1:A` or `A1:1`. These are supported by Google Sheets but not Excel. See: References.md.
|
|
555
556
|
* @param [options.mergeRefs=true] Should ranges be treated as whole references (`Sheet1!A1:B2`) or as separate tokens for each part: (`Sheet1`,`!`,`A1`,`:`,`B2`).
|
|
556
557
|
* @param [options.wrapEdges=true] Wrap out-of-bounds ranges around sheet edges rather than turning them to #REF! errors
|
|
557
558
|
* @param [options.xlsx=false] Switches to the `[1]Sheet1!A1` or `[1]!name` prefix syntax form for external workbooks. See: [Prefixes.md](./Prefixes.md)
|
|
558
559
|
* @returns A formula string or token list (depending on which was input)
|
|
559
560
|
*/
|
|
560
561
|
export declare function translateToA1(formula: (string | Array<object>), anchorCell: string, options?: {
|
|
562
|
+
/** Enables the recognition of ternary ranges in the style of `A1:A` or `A1:1`. These are supported by Google Sheets but not Excel. See: References.md. */
|
|
563
|
+
allowTernary?: boolean;
|
|
561
564
|
/** Should ranges be treated as whole references (`Sheet1!A1:B2`) or as separate tokens for each part: (`Sheet1`,`!`,`A1`,`:`,`B2`). */
|
|
562
565
|
mergeRefs?: boolean;
|
|
563
566
|
/** Wrap out-of-bounds ranges around sheet edges rather than turning them to #REF! errors */
|
|
@@ -579,10 +582,13 @@ export declare function translateToA1(formula: (string | Array<object>), anchorC
|
|
|
579
582
|
* @param formula A string (an Excel formula) or a token list that should be adjusted.
|
|
580
583
|
* @param anchorCell A simple string reference to an A1 cell ID (`AF123` or`$C$5`).
|
|
581
584
|
* @param [options={}] The options
|
|
585
|
+
* @param [options.allowTernary=true] Enables the recognition of ternary ranges in the style of `A1:A` or `A1:1`. These are supported by Google Sheets but not Excel. See: References.md.
|
|
582
586
|
* @param [options.xlsx=false] Switches to the `[1]Sheet1!A1` or `[1]!name` prefix syntax form for external workbooks. See: [Prefixes.md](./Prefixes.md)
|
|
583
587
|
* @returns A formula string or token list (depending on which was input)
|
|
584
588
|
*/
|
|
585
589
|
export declare function translateToR1C1(formula: (string | Array<object>), anchorCell: string, options?: {
|
|
590
|
+
/** Enables the recognition of ternary ranges in the style of `A1:A` or `A1:1`. These are supported by Google Sheets but not Excel. See: References.md. */
|
|
591
|
+
allowTernary?: boolean;
|
|
586
592
|
/** Switches to the `[1]Sheet1!A1` or `[1]!name` prefix syntax form for external workbooks. See: [Prefixes.md](./Prefixes.md) */
|
|
587
593
|
xlsx?: boolean;
|
|
588
594
|
}): (string | Array<object>);
|
package/dist/fx.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";const e="operator",t="error",n="range_beam",l="range_ternary",r="range_named",o="structured",u="unknown",s="UnaryExpression",i="BinaryExpression",c="ReferenceIdentifier",a="CallExpression";function f(e){let t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=!1,l="";const r=[],o=()=>{l&&r.push(t?l:{value:l,braced:n}),l=""};for(let t=0;t<e.length;t++){const r=e[t];"["===r?(o(),n=!0):"]"===r?(o(),n=!1):l+=r}return o(),r}function p(e){return{context:f(e,!0)}}function h(e){const t={},n=f(e);if(n.length>1)t.workbookName=n[n.length-2].value,t.sheetName=n[n.length-1].value;else if(1===n.length){const e=n[0];e.braced?t.workbookName=e.value:t.sheetName=e.value}return t}const g=e=>e&&":"===e.value&&{},x=e=>e&&"range"===e.type&&{r0:e.value},d=e=>e&&e.type===l&&{r0:e.value},m=e=>e&&"range"===e.type&&{r1:e.value},$=t=>t&&t.type===e&&"!"===t.value&&{},y=e=>e&&e.type===n&&{r0:e.value},v=e=>e&&e.type===o&&{struct:e.value},E=(e,t)=>{const n=t.xlsx?h:p;return e&&"context"===e.type?n(e.value):e&&"context_quote"===e.type?n(e.value.slice(1,-1).replace(/''/g,"'")):void 0},R=e=>e&&e.type===r&&{name:e.value},w=[[d],[x,g,m],[x],[y],[E,$,d],[E,$,x,g,m],[E,$,x],[E,$,y]],N=w.concat([[R],[E,$,R],[v],[R,v],[E,$,R,v]]);function b(e,t){const n={withLocation:!1,mergeRefs:!1,allowTernary:!1,allowNamed:!0,r1c1:!1,xlsx:!1,...t},l=Oe(e,we,n),r=n.xlsx?{workbookName:"",sheetName:"",r0:"",r1:"",name:""}:{context:[],r0:"",r1:"",name:""};l.length&&"fx_prefix"===l[0].type&&l.shift();const o=n.allowNamed?N:w;for(let e=0;e<o.length;e++){const t={...r};if(o[e].length===l.length){const r=o[e].every(((e,r)=>{const o=e(l[r],n);return Object.assign(t,o),o}));if(r)return t}}return null}const C=/[^0-9A-Za-z._¡¤§¨ª\u00ad¯-\uffff]/;function A(e){let t="",n=0,l=0;const r=e.context||[];for(let e=r.length;e>-1;e--){const o=r[e];if(o){t=(l%2?"["+o+"]":o)+t,n+=C.test(o),l++}}return n&&(t="'"+t.replace(/'/g,"''")+"'"),t?t+"!":t}function T(e){let t="",n=0;const{workbookName:l,sheetName:r}=e;return l&&(t+="["+l+"]",n+=C.test(l)),r&&(t+=r,n+=C.test(r)),n&&(t="'"+t.replace(/'/g,"''")+"'"),t?t+"!":t}const I=(e,t,n)=>Math.min(Math.max(t,e),n),L=(e,t)=>(t?"$":"")+_(e),k=(e,t)=>(t?"$":"")+String(e+1);function O(e){const t=e||"",n=t.length;let l=0;if(n>2){const e=t.charCodeAt(n-3);l+=676*(1+e-(e>95?32:0)-65)}if(n>1){const e=t.charCodeAt(n-2);l+=26*(1+e-(e>95?32:0)-65)}if(n){const e=t.charCodeAt(n-1);l+=e-(e>95?32:0)-65}return l}function _(e){return(e>=702?String.fromCharCode(((e-702)/676-0)%26+65):"")+(e>=26?String.fromCharCode(Math.floor((e/26-1)%26+65)):"")+String.fromCharCode(e%26+65)}function U(e){let{top:t,left:n,bottom:l,right:r}=e;const{$left:o,$right:u,$top:s,$bottom:i}=e,c=null==n,a=null==r,f=null==t,p=null==l;return t=I(0,0|t,1048575),n=I(0,0|n,16383),!c&&!f&&a&&p?(l=t,r=n):(l=I(0,0|l,1048575),r=I(0,0|r,16383)),0===t&&l>=1048575||f&&p?L(n,o)+":"+L(r,u):0===n&&r>=16383||c&&a?k(t,s)+":"+k(l,i):c||f||a||!p?c||!f||a||p?c||f||!a||p?!c||f||a||p?r!==n||l!==t||u!==o||i!==s?L(n,o)+k(t,s)+":"+L(r,u)+k(l,i):L(n,o)+k(t,s):L(r,u)+k(t,s)+":"+k(l,i):L(n,o)+k(t,s)+":"+k(l,i):L(n,o)+k(l,i)+":"+L(r,u):L(n,o)+k(t,s)+":"+L(r,u)}function F(e){const t=/^(?=.)(\$(?=\D))?([A-Za-z]{0,3})?(\$)?([1-9][0-9]{0,6})?$/.exec(e);return t&&(t[2]||t[4])?[t[4]?(n=t[4],+n-1):null,t[2]?O(t[2]):null,!!t[3],!!t[1]]:null;var n}function S(e){let t=null,n=null,l=null,r=null,o=!1,u=!1,s=!1,i=!1;const[c,a,f]=e.split(":");if(f)return null;const p=F(c),h=a?F(a):null;if(!p||a&&!h)return null;if(null!=p[0]&&null!=p[1]?[t,n,o,u]=p:null==p[0]&&null!=p[1]?[,n,,u]=p:null!=p[0]&&null==p[1]&&([t,,o]=p),a)null!=h[0]&&null!=h[1]?[l,r,s,i]=h:null==h[0]&&null!=h[1]?[,r,,i]=h:null!=h[0]&&null==h[1]&&([l,,s]=h);else{if(null==t||null==n)return null;l=t,r=n,s=o,i=u}return null!=r&&(null==n||null!=n&&r<n)&&([n,r,u,i]=[r,n,i,u]),null!=l&&(null==t||null!=t&&l<t)&&([t,l,o,s]=[l,t,s,o]),{top:t,left:n,bottom:l,right:r,$top:o,$left:u,$bottom:s,$right:i}}function M(e){let{allowNamed:t=!0,allowTernary:n=!1,xlsx:l=!1}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const r=b(e,{allowNamed:t,allowTernary:n,xlsx:l,r1c1:!1});if(r&&(r.r0||r.name)){let e=null;return r.r0&&(e=S(r.r1?r.r0+":"+r.r1:r.r0)),r.name||e?(r.range=e,delete r.r0,delete r.r1,r):null}return null}function D(e){let{xlsx:t=!1}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const n=t?T(e):A(e);return n+(e.name?e.name:U(e.range))}function j(e){return null==e.top&&(e.top=0,e.$top=!1),null==e.bottom&&(e.bottom=1048575,e.$bottom=!1),null==e.left&&(e.left=0,e.$left=!1),null==e.right&&(e.right=16383,e.$right=!1),e}const z=/^\[('['#@[\]]|[^'#@[\]])+\]/i,W=/^([^#@[\]:]+)/i,Z={headers:1,data:2,totals:4,all:8,"this row":16,"@":16},q=function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return Object.freeze(t)},B={0:q(),1:q("headers"),2:q("data"),4:q("totals"),8:q("all"),16:q("this row"),3:q("headers","data"),6:q("data","totals")},P=function(e){let t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=z.exec(e);if(n){const e=n[0].slice(1,-1).replace(/'(['#@[\]])/g,"$1");return[n[0],e]}return t&&(n=W.exec(e),n)?[n[0],n[0]]:null};function X(e){const t=[];let n,l,r=0,o=e,u=0;if(!(n=/^(\[\s*)/.exec(o)))return null;if(l=/^\[#([a-z ]+)\]/i.exec(o)){const e=l[1].toLowerCase();if(r+=l[0].length,!Z[e])return null;u|=Z[e]}else if(l=P(o,!1))r+=l[0].length,t.push(l[1].trim());else{let l=!0;for(o=o.slice(n[1].length),r+=n[1].length;l&&(n=/^\[#([a-z ]+)\](\s*,\s*)?/i.exec(o));){const e=n[1].toLowerCase();if(!Z[e])return null;u|=Z[e],o=o.slice(n[0].length),r+=n[0].length,l=!!n[2]}if(l&&(n=/^@/.exec(o))&&(u|=Z["@"],o=o.slice(1),r+=1,l="]"!==o[0]),!(u in B))return null;const s=l?P(e.slice(r)):null;if(s){if(r+=s[0].length,t.push(s[1].trim()),o=e.slice(r),":"===o[0]){o=o.slice(1),r++;const e=P(o);if(!e)return null;r+=e[0].length,t.push(e[1].trim())}l=!1}for(;" "===e[r];)r++;if(l||"]"!==e[r])return null;r++}const s=B[u];return{columns:t,sections:s?s.concat():s,length:r,token:e.slice(0,r)}}function H(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{xlsx:!1};const n=b(e,t);if(n&&n.struct){const e=X(n.struct);if(e&&e.length===n.struct.length)return t.xlsx?{workbookName:n.workbookName,sheetName:n.sheetName,table:n.name,columns:e.columns,sections:e.sections}:{context:n.context,table:n.name,columns:e.columns,sections:e.sections}}return null}function Y(e){return e.replace(/([[\]#'@])/g,"'$1")}function G(e){return!/^[a-zA-Z0-9\u00a1-\uffff]+$/.test(e)}function K(e){return e[0].toUpperCase()+e.slice(1).toLowerCase()}function V(e){let{xlsx:t=!1}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t?T(e):A(e);e.table&&(n+=e.table);const l=e.columns?.length??0,r=e.sections?.length??0;if(1!==r||l)if(r||1!==l){n+="[";const t=1===r&&"this row"===e.sections[0].toLowerCase();t?n+="@":r&&(n+=e.sections.map((e=>`[#${K(e)}]`)).join(","),l&&(n+=",")),t&&1===e.columns.length&&!G(e.columns[0])?n+=Y(e.columns[0]):l&&(n+=e.columns.slice(0,2).map((e=>`[${Y(e)}]`)).join(":")),n+="]"}else n+=`[${Y(e.columns[0])}]`;else n+=`[#${K(e.sections[0])}]`;return n}const Q=/^(?!!)(\[(?:[^\]])+\])?([0-9A-Za-z._¡¤§¨ª\u00ad¯-\uffff]+)?(?=!)/,J=/^'(?:''|[^'])*('|$)(?=!)/,ee="\\$?[A-Z]{1,3}\\$?[1-9][0-9]{0,6}",te="\\$?[A-Z]{1,3}",ne="\\$?[1-9][0-9]{0,6}",le=new RegExp(`^${te}:${te}`,"i"),re=new RegExp(`^${ne}:${ne}`,"i"),oe=new RegExp(`^${ee}`,"i"),ue=new RegExp(`^((${te}|${ne}):${ee}|${ee}:(${te}|${ne}))(?![\\w($.])`,"i"),se="(?:R(?:\\[[+-]?\\d+\\]|[1-9][0-9]{0,6})?)",ie="(?:C(?:\\[[+-]?\\d+\\]|[1-9][0-9]{0,4})?)",ce=new RegExp(`^${ie}(:${ie})?(?=\\W|$)`,"i"),ae=new RegExp(`^${se}(:${se})?(?=\\W|$)`,"i"),fe=new RegExp(`^(?:(?=[RC])${se}${ie})`,"i"),pe=new RegExp(`^(${se}${ie}(:${ie}|:${se})(?![[\\d])|(${se}|${ie})(:${se}${ie}))(?=\\W|$)`,"i"),he=/^(?![CR]\b)[a-zA-Z\\_\u00a1-\uffff][a-zA-Z0-9\\_.?\u00a1-\uffff]{0,254}/i;function ge(e,t){return n=>{const l=t.exec(n);if(l)return{type:e,value:l[0]}}}const xe=/^'(?:[^[\]]+?)?(?:\[(.+?)\])?(?:[^[\]]+?)'$/,de=/^'\[(.+?)\]'$/;function me(e,t){const n=J.exec(e);if(n){const e=n[0];if(t.xlsx&&de.test(e)||xe.test(e))return{type:"context_quote",value:e}}const l=Q.exec(e);if(l){const[,e,n]=l;if(e&&n||n||e&&!n&&t.xlsx)return{type:"context",value:l[0]}}}function $e(e){const t=X(e);if(t){let n=t.length;for(;" "===e[n];)n++;if("!"!==e[n])return{type:o,value:t.token}}return null}const ye=/([RC])(\[?)(-?\d+)/gi,ve=/(\d+|[a-zA-Z]+)/gi;function Ee(e,t){let r,o;if(t.r1c1){if(t.allowTernary&&(r=pe.exec(e))?o={type:l,value:r[0]}:(r=fe.exec(e))?o={type:"range",value:r[0]}:((r=ae.exec(e))||(r=ce.exec(e)))&&(o={type:n,value:r[0]}),o){for(ye.lastIndex=0;null!==(r=ye.exec(o.value));){const e=("R"===r[1]?1048575:16383)+(r[2]?1:0),t=parseInt(r[3],10);if(t>=e||t<=-e)return null}return o}}else if(t.allowTernary&&(r=ue.exec(e))?o={type:l,value:r[0]}:(r=le.exec(e))||(r=re.exec(e))?o={type:n,value:r[0]}:(r=oe.exec(e))&&(o={type:"range",value:r[0]}),o){for(ve.lastIndex=0;null!==(r=ve.exec(o.value));)if(/^\d/.test(r[1])){if(parseInt(r[1],10)-1>1048575)return null}else if(O(r[1])>16383)return null;return o}}const Re=[ge(t,/^#(NAME\?|FIELD!|CALC!|VALUE!|REF!|DIV\/0!|NULL!|NUM!|N\/A|GETTING_DATA\b|SPILL!|UNKNOWN!|FIELD\b|CALC\b|SYNTAX\?|ERROR!|CONNECT!|BLOCKED!|EXTERNAL!)/i),ge(e,/^(<=|>=|<>|[-+/*^%&<>=]|[{},;]|[()]|@|:|!|#)/),ge("func",/^[A-Z_]+[A-Z\d_.]*(?=\()/i),ge("bool",/^(TRUE|FALSE)\b/i),ge("newline",/^\n+/),ge("whitespace",/^[ \f\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/),ge("string",/^"(?:""|[^"])*("|$)/),me,Ee,$e,ge("number",/^(?:\d+(\.\d+)?(?:[eE][+-]?\d+)?|\d+)/),ge(r,he)],we=[function(t,n){return n.r1c1?"!"===t[0]?{type:e,value:t[0]}:null:"!"===t[0]||":"===t[0]?{type:e,value:t[0]}:null},me,Ee,$e,ge(r,he)],Ne={};function be(e,t){if(e.length){const n=e[0];t[n]=t[n]||{},be(e.slice(1),t[n])}else t.$=!0}[["range",":","range"],["range"],[n],[l],["context","!","range",":","range"],["context","!","range"],["context","!",n],["context","!",l],["context_quote","!","range",":","range"],["context_quote","!","range"],["context_quote","!",n],["context_quote","!",l],[r],["context","!",r],["context_quote","!",r],[o],[r,o],["context","!",r,o],["context_quote","!",r,o]].forEach((e=>be(e.concat().reverse(),Ne)));const Ce=function(t,n,l){let r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0;const o=t[l-r];if(o){const u=o.type===e?o.value:o.type;if(u in n)return Ce(t,n[u],l,r+1)}return n.$?r:0};function Ae(e){const t=[];for(let n=e.length-1;n>=0;n--){let l=e[n];const r=Ce(e,Ne,n);if(r){const t=e.slice(n-r+1,n+1);l={...l},l.value=t.map((e=>e.value)).join(""),l.loc&&t[0].loc&&(l.loc[0]=t[0].loc[0]),n-=r-1}t.unshift(l)}return t}const Te=(e,t)=>e&&e.type===t,Ie={withLocation:!1,mergeRefs:!0,allowTernary:!1,negativeNumbers:!0,r1c1:!1},Le=e=>e.type===r||"func"===e.type,ke=t=>!Te(t,e)||"%"===t.value||"}"===t.value||")"===t.value||"#"===t.value;function Oe(t,n){let l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};const r=Object.assign({},Ie,l),{withLocation:o,mergeRefs:s,negativeNumbers:i}=r,c=[];let a=0,f=null,p=null,h=null;const g=e=>{const t=e.type===u,n=h&&h.type===u;h&&(t&&n||t&&Le(h)||n&&Le(e))?(h.value+=e.value,h.type=u,o&&(h.loc[1]=e.loc[1])):(c.push(e),h=e,"whitespace"!==e.type&&"newline"!==e.type&&(p=f,f=e))};if(/^=/.test(t)){a++,g({type:"fx_prefix",value:"=",...o?{loc:[0,1]}:{}})}for(;a<t.length;){const l=a,s=t.slice(a);let x="",d="";for(let e=0;e<n.length;e++){const t=n[e](s,r);if(t){x=t.type,d=t.value,a+=d.length;break}}x||(x=u,d=t[a],a++);const m={type:x,value:d,...o?{loc:[l,a]}:{}};if("string"===x){const e=d.length;if('""'===d);else if('"'===d||'"'!==d[e-1])m.unterminated=!0;else if('""'!==d&&'"'===d[e-2]){let t=e-1;for(;'"'===d[t];)t--;!(t+1)^(e-t+1)%2==0&&(m.unterminated=!0)}}if(i&&"number"===x){const t=h;if(t&&Te(t,e)&&"-"===t.value&&(!p||Te(p,"fx_prefix")||!ke(p))){const e=c.pop();m.value="-"+d,o&&(m.loc[0]=e.loc[0]),f=p,h=c[c.length-1]}}g(m)}return s?Ae(c):c}function _e(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return Oe(e,Re,t)}function Ue(e){return!!e&&("range"===e.type||e.type===n||e.type===l)}function Fe(e){return!!e&&("range"===e.type||e.type===n||e.type===l||e.type===o||e.type===r)}function Se(e){return!!e&&("bool"===e.type||e.type===t||"number"===e.type||"string"===e.type)}function Me(e){return!!e&&e.type===t}function De(e){return!!e&&("whitespace"===e.type||"newline"===e.type)}function je(e){return!!e&&"func"===e.type}function ze(e){return!!e&&"fx_prefix"===e.type}function We(t){return!!t&&t.type===e}const Ze="(END)",qe=["ANCHORARRAY","CHOOSE","DROP","IF","IFS","INDEX","INDIRECT","LAMBDA","LET","OFFSET","REDUCE","SINGLE","SWITCH","TAKE","XLOOKUP"],Be=e=>!!e&&(e.type===c||("ErrorLiteral"===e.type||e.type===t)&&"#REF!"===e.value||e.type===i&&(":"===e.operator||" "===e.operator||","===e.operator)||e.type===a&&qe.includes(e.callee.name.toUpperCase())),Pe={};let Xe,He,Ye,Ge=!1,Ke=!1;function Ve(e){const t=new Error(e);throw t.source=He.map((e=>e.value)).join(""),t.sourceOffset=He.slice(0,Ye).reduce(((e,t)=>e+t.value),"").length,t}function Qe(){let e,t=Ye;do{e=He[++t]}while(e&&(De(e)||We(e)&&"("===e.value));return(e=>{const t=(e&&e.value)+"";return!(!Fe(e)&&(!We(e)||":"!==t&&","!==t&&t.trim())&&(!je(e)||!qe.includes(t.toUpperCase()))&&(!Me(e)||"#REF!"!==t))})(e)}function Je(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;if(e&&e!==Xe.id&&Ve(`Expected ${e} but got ${Xe.id}`),De(He[Ye])){if(!(Be(t)&&Qe()))for(;De(He[Ye]);)Ye++}if(Ye>=He.length)return void(Xe=Pe[Ze]);const n=He[Ye];let l;Ye+=1,n.unterminated&&Ve("Encountered an unterminated token");let r=n.type;return We(n)?(l=Pe[n.value],l||Ve(`Unknown operator ${n.value}`)):De(n)?l=Pe["(WHITESPACE)"]:Se(n)?l=Pe.Literal:Fe(n)?(l=Pe[c],r=c):je(n)?l=Pe["(FUNCTION)"]:Ve(`Unexpected ${n.type} token: ${n.value}`),Xe=Object.create(l),Xe.type=r,Xe.value=n.value,n.loc&&(Xe.loc=[...n.loc]),Xe}function et(e){let t=Xe;Je(null,t);let n=t.nud();for(;e<Xe.lbp;)t=Xe,Je(null,t),n=t.led(n);return n}const tt={nud:()=>Ve("Invalid syntax"),led:()=>Ve("Missing operator")};function nt(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=Pe[e];return n?t>=n.lbp&&(n.lbp=t):(n={...tt},n.id=e,n.value=e,n.lbp=t,Pe[e]=n),n}function lt(e,t,n){const l=nt(e,t);return l.led=n||function(e){this.type=i,this.operator=this.value,delete this.value;const n=et(t);return this.arguments=[e,n],this.loc&&(this.loc=[e.loc[0],n.loc[1]]),this},l}function rt(e,t){const n=nt(e,0);return n.lbp=70,n.led=t||function(e){return this.type=s,this.operator=this.value,delete this.value,this.arguments=[e],this.loc&&(this.loc[0]=e.loc[0]),this},n}function ot(e,t){const n=nt(e);return n.nud=t||function(){this.type=s,this.operator=this.value,delete this.value;const e=et(70);return this.arguments=[e],this.loc&&(this.loc[1]=e.loc[1]),this},n}function ut(e,t){return lt(e,t,(function(n){Be(n)||Ve(`Unexpected ${e} operator`);const l=et(t);return Be(l)||Ve(`Unexpected ${Xe.type} following ${this.id}`),this.type=i,this.operator=this.value.trim()?this.value:" ",delete this.value,this.arguments=[n,l],this.loc&&(this.loc=[n.loc[0],l.loc[1]]),this}))}nt(Ze),ut(":",80);const st=ut(",",80);ut("(WHITESPACE)",80);const it=e=>{const t=st.lbp>0;return null!=e&&(st.lbp=e?80:0),t};function ct(){let e=1;return()=>"fxg"+e++}function at(e,t){return null==e&&null==t||e===t}function ft(e,t){if(Array.isArray(e)!==Array.isArray(t)||e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(!at(e[n],t[n]))return!1;return!0}function pt(e,t){return!e&&!t||String(e).toLowerCase()===String(t).toLowerCase()}function ht(e,t){if((e.name||t.name)&&e.name!==t.name)return!1;if(e.columns||t.columns){if(e.table!==t.table)return!1;if(!ft(e.columns,t.columns))return!1;if(!ft(e.sections,t.sections))return!1}return!!(!e.range&&!t.range||at(e.range.top,t.range.top)&&at(e.range.bottom,t.range.bottom)&&at(e.range.left,t.range.left)&&at(e.range.right,t.range.right))&&!(!pt(e.workbookName,t.workbookName)||!pt(e.sheetName,t.sheetName))}function gt(e,t,n){return e.sheetName||(e.sheetName=t),e.workbookName||(e.workbookName=n),e}rt("%"),rt("#",(function(e){return Be(e)||Ve("# expects a reference"),this.type=s,this.operator=this.value,delete this.value,this.arguments=[e],this})),ot("+"),ot("-"),ot("@"),lt("^",50),lt("*",40),lt("/",40),lt("+",30),lt("-",30),lt("&",20),lt("=",10),lt("<",10),lt(">",10),lt("<=",10),lt(">=",10),lt("<>",10),nt("Literal").nud=function(){const{type:e,value:n}=this;if(this.type="Literal",this.raw=n,"number"===e)this.value=+n;else if("bool"===e)this.value="TRUE"===n.toUpperCase();else if(e===t)this.type="ErrorLiteral",this.value=n.toUpperCase();else{if("string"!==e)throw new Error("Unsupported literal type: "+e);this.value=n.slice(1,-1).replace(/""/g,'"')}return this},nt(c).nud=function(){return this.type=c,this},nt(")"),ot("(",(function(){const e=it(!0),t=et(0);return Je(")",t),it(e),t})),nt("(FUNCTION)").nud=function(){return this},lt("(",90,(function(e){"(FUNCTION)"!==e.id&&Ve("Cannot call a "+e.type);const t=[];let n=!1;if(")"!==Xe.id){const e=it(!1);for(;")"!==Xe.id;)if(De(Xe)&&Je(),","===Xe.id)t.push(null),n=!0,Je();else{const e=et(0);t.push(e),n=!1,","===Xe.id&&(Je(","),n=!0)}it(e)}n&&t.push(null);const l=Xe;return delete this.value,this.type=a,this.callee={type:"Identifier",name:e.value},e.loc&&(this.callee.loc=[...e.loc]),this.arguments=t,e.loc&&(this.loc=[e.loc[0],l.loc[1]]),Je(")",this),this})),nt("}"),nt(";"),ot("{",(function(){"}"===Xe.id&&Ve("Unexpected empty array");let e=[],t=!1;const n=[e],l=it(!1);for(;!t;){if(De(Xe)&&Je(),Se(Xe))e.push(Pe.Literal.nud.call(Xe)),Je();else if(Ge&&Be(Xe))e.push(Pe[c].nud.call(Xe)),Je();else if(Ke&&je(Xe)){const t=et(0);e.push(t)}else Ve(`Unexpected ${Xe.type} in array: ${Xe.value}`);","===Xe.id?Je(","):";"===Xe.id?(Je(";"),e=[],n.push(e)):t=!0}const r=Xe;return Je("}"),it(l),this.type="ArrayExpression",this.elements=n,this.loc&&(this.loc[1]=r.loc[1]),delete this.value,this}));const xt=(e,t,n)=>Math.min(Math.max(t,e),n);function dt(e,t){return t?String(e+1):e?"["+e+"]":""}function mt(e){let{r0:t,c0:n,r1:l,c1:r}=e;const{$c0:o,$c1:u,$r0:s,$r1:i}=e,c=null==t,a=null==n;let f=null==l,p=null==r;if(t=xt(s?0:-1048575,0|t,1048575),n=xt(o?0:-16383,0|n,16383),!c&&f&&!a&&p?(l=t,f=!1,r=n,p=!1):(l=xt(i?0:-1048575,0|l,1048575),r=xt(u?0:-16383,0|r,16383)),0===t&&l>=1048575||c&&f){const e=dt(n,o),t=dt(r,u);return"C"+(e===t?e:e+":C"+t)}if(0===n&&r>=16383||a&&p){const e=dt(t,s),n=dt(l,i);return"R"+(e===n?e:e+":R"+n)}const h=dt(t,s),g=dt(l,i),x=dt(n,o),d=dt(r,u);return c||f||a||p?(c?"":"R"+h)+(a?"":"C"+x)+":"+(f?"":"R"+g)+(p?"":"C"+d):h!==g||x!==d?"R"+h+"C"+x+":R"+g+"C"+d:"R"+h+"C"+x}function $t(e){let t=null,n=null,l=null,r=null;const o=/^R(?:\[([+-]?\d+)\]|(\d+))?/.exec(e);o&&(o[1]?(t=parseInt(o[1],10),l=!1):o[2]?(t=parseInt(o[2],10)-1,l=!0):(t=0,l=!1),e=e.slice(o[0].length));const u=/^C(?:\[([+-]?\d+)\]|(\d+))?/.exec(e);return u&&(u[1]?(n=parseInt(u[1],10),r=!1):u[2]?(n=parseInt(u[2],10)-1,r=!0):(n=0,r=!1),e=e.slice(u[0].length)),!o&&!u||e.length?null:[t,n,l,r]}function yt(e){let t=null;const[n,l]=e.split(":",2),r=$t(n);if(r){const[e,n,o,u]=r;if(!l)return null!=e&&null==n?{r0:e,c0:null,r1:e,c1:null,$r0:o,$c0:!1,$r1:o,$c1:!1}:null==e&&null!=n?{r0:null,c0:n,r1:null,c1:n,$r0:!1,$c0:u,$r1:!1,$c1:u}:{r0:e||0,c0:n||0,r1:e||0,c1:n||0,$r0:o||!1,$c0:u||!1,$r1:o||!1,$c1:u||!1};{const r=$t(l);if(!r)return null;{t={};const[l,s,i,c]=r;null!=e&&null!=l?(t.r0=o===i?Math.min(e,l):e,t.$r0=o,t.r1=o===i?Math.max(e,l):l,t.$r1=i):null!=e&&null==l?(t.r0=e,t.$r0=o,t.r1=null,t.$r1=o):null==e&&null!=l?(t.r0=l,t.$r0=i,t.r1=null,t.$r1=i):null==e&&null==l&&(t.r0=null,t.$r0=!1,t.r1=null,t.$r1=!1),null!=n&&null!=s?(t.c0=u===c?Math.min(n,s):n,t.$c0=u,t.c1=u===c?Math.max(n,s):s,t.$c1=c):null!=n&&null==s?(t.c0=n,t.$c0=u,t.c1=null,t.$c1=u):null==n&&null!=s?(t.c0=s,t.$c0=c,t.c1=null,t.$c1=c):null==n&&null==s&&(t.c0=null,t.$c0=!1,t.c1=null,t.$c1=!1)}}}return t}function vt(e){let{allowNamed:t=!0,allowTernary:n=!1,xlsx:l=!1}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const r=b(e,{allowNamed:t,allowTernary:n,xlsx:l,r1c1:!0});if(r&&(r.r0||r.name)){const e=r.r1?yt(r.r0+":"+r.r1):yt(r.r0);return r.name||e?(r.range=e,delete r.r0,delete r.r1,r):null}return null}function Et(e){let{xlsx:t=!1}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const n=t?T(e):A(e);return n+(e.name?e.name:mt(e.range))}const Rt=(e,t,n)=>null==t?null:e?t:t-n,wt={withLocation:!1,mergeRefs:!1,allowTernary:!0,r1c1:!1};function Nt(e,t,n,l){let r=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],o=e;if(null!=o&&!t){if(o=n+e,o<0){if(!r)return NaN;o=l+o+1}if(o>l){if(!r)return NaN;o-=l+1}}return o}const bt={wrapEdges:!0,mergeRefs:!0,xlsx:!1};const Ct=Object.freeze({OPERATOR:e,BOOLEAN:"bool",ERROR:t,NUMBER:"number",FUNCTION:"func",NEWLINE:"newline",WHITESPACE:"whitespace",STRING:"string",CONTEXT:"context",CONTEXT_QUOTE:"context_quote",REF_RANGE:"range",REF_BEAM:n,REF_TERNARY:l,REF_NAMED:r,REF_STRUCT:o,FX_PREFIX:"fx_prefix",UNKNOWN:u}),At=Object.freeze({UNARY:s,BINARY:i,REFERENCE:c,LITERAL:"Literal",ERROR:"ErrorLiteral",CALL:a,ARRAY:"ArrayExpression",IDENTIFIER:"Identifier"});exports.MAX_COLS=16383,exports.MAX_ROWS=1048575,exports.addA1RangeBounds=j,exports.addTokenMeta=function(e){let{sheetName:t="",workbookName:r=""}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const s=[];let i=null;const c=ct(),a=[],f=()=>s.length+(i?1:0);return e.forEach(((e,p)=>{if(e.index=p,e.depth=f(),"("===e.value)s.push(e),e.depth=f();else if(")"===e.value){const t=s.pop();if(t){const n=c();e.groupId=n,e.depth=t.depth,t.groupId=n}else e.error=!0}else if("{"===e.value)i?e.error=!0:(i=e,e.depth=f());else if("}"===e.value){if(i){const t=c();e.groupId=t,e.depth=i.depth,i.groupId=t}else e.error=!0;i=null}else if("range"===e.type||e.type===n||e.type===l||e.type===o){const n=e.type===o?H(e.value,{allowTernary:!0,xlsx:!0}):M(e.value,{allowTernary:!0,xlsx:!0});if(n&&(n.range||n.columns)){n.source=e.value,gt(n,t,r);const l=a.find((e=>ht(e,n)));l?e.groupId=l.groupId:(n.groupId=c(),e.groupId=n.groupId,a.push(n))}}else e.type===u&&(e.error=!0)})),e},exports.fixRanges=function e(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{addBounds:!1};if("string"==typeof t)return e(_e(t,n),n).map((e=>e.value)).join("");if(!Array.isArray(t))throw new Error("fixRanges expects an array of tokens");const{addBounds:l,r1c1:r,xlsx:u}=n;if(r)throw new Error("fixRanges does not have an R1C1 mode");let s=0;return t.map((e=>{const t={...e};e.loc&&(t.loc=[...e.loc]);let n=0;if(t.type===o){const e=V(H(t.value,{xlsx:u}),{xlsx:u});n=e.length-t.value.length,t.value=e}else if(Ue(t)){const e=M(t.value,{xlsx:u,allowTernary:!0}),r=e.range;l&&j(r);const o=D(e,{xlsx:u});n=o.length-t.value.length,t.value=o}return s||n?(t.loc&&(t.loc[0]+=s),s+=n,t.loc&&(t.loc[1]+=s)):s+=n,t}))},exports.fromCol=O,exports.isError=Me,exports.isFunction=je,exports.isFxPrefix=ze,exports.isLiteral=Se,exports.isOperator=We,exports.isRange=Ue,exports.isReference=Fe,exports.isWhitespace=De,exports.mergeRefTokens=Ae,exports.nodeTypes=At,exports.parse=function(e,t){if("string"==typeof e)He=_e(e,{withLocation:!1,...t,mergeRefs:!0});else{if(!Array.isArray(e))throw new Error("Parse requires a string or array of tokens.");He=e}for(Ge=t?.permitArrayRanges,Ke=t?.permitArrayCalls,Ye=0;De(He[Ye])||ze(He[Ye]);)Ye++;Je(),it(!0);const n=et(0);return Je(Ze),n},exports.parseA1Ref=M,exports.parseR1C1Ref=vt,exports.parseStructRef=H,exports.stringifyA1Ref=D,exports.stringifyR1C1Ref=Et,exports.stringifyStructRef=V,exports.toCol=_,exports.tokenTypes=Ct,exports.tokenize=_e,exports.translateToA1=function(e,n){let l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:bt;const r=S(n),o="string"==typeof e,u={...bt,...l},s=o?_e(e,{withLocation:!1,mergeRefs:u.mergeRefs,xlsx:u.xlsx,allowTernary:!0,r1c1:!0}):e;let i=0;const c={xlsx:u.xlsx,allowTernary:!0};return s.forEach((e=>{if(Ue(e)){const n=e.value,l=vt(n,c),o=l.range,s={},a=Nt(o.r0,o.$r0,r.top,1048575,u.wrapEdges),f=Nt(o.r1,o.$r1,r.top,1048575,u.wrapEdges);a>f?(s.top=f,s.$top=o.$r1,s.bottom=a,s.$bottom=o.$r0):(s.top=a,s.$top=o.$r0,s.bottom=f,s.$bottom=o.$r1);const p=Nt(o.c0,o.$c0,r.left,16383,u.wrapEdges),h=Nt(o.c1,o.$c1,r.left,16383,u.wrapEdges);p>h?(s.left=h,s.$left=o.$c1,s.right=p,s.$right=o.$c0):(s.left=p,s.$left=o.$c0,s.right=h,s.$right=o.$c1),isNaN(a)||isNaN(f)||isNaN(p)||isNaN(h)?(e.type=t,e.value="#REF!",delete e.groupId):(l.range=s,e.value=D(l,c)),e.loc&&(e.loc[0]+=i,i+=e.value.length-n.length,e.loc[1]+=i)}else i&&e.loc&&(e.loc[0]+=i,e.loc[1]+=i)})),o?s.map((e=>e.value)).join(""):s},exports.translateToR1C1=function(e,t){let{xlsx:n=!1}=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};const{top:l,left:r}=S(t),o="string"==typeof e,u=o?_e(e,{...wt,xlsx:n}):e;let s=0;const i={xlsx:n,allowTernary:!0};return u.forEach((e=>{if(Ue(e)){const t=e.value,n=M(t,i),o=n.range,u={};u.r0=Rt(o.$top,o.top,l),u.r1=Rt(o.$bottom,o.bottom,l),u.c0=Rt(o.$left,o.left,r),u.c1=Rt(o.$right,o.right,r),u.$r0=o.$top,u.$r1=o.$bottom,u.$c0=o.$left,u.$c1=o.$right,n.range=u,e.value=Et(n,i),e.loc&&(e.loc[0]+=s,s+=e.value.length-t.length,e.loc[1]+=s)}else s&&e.loc&&(e.loc[0]+=s,e.loc[1]+=s)})),o?u.map((e=>e.value)).join(""):u};
|
|
1
|
+
"use strict";const e="operator",t="error",n="range_beam",l="range_ternary",r="range_named",o="structured",u="unknown",s="UnaryExpression",c="BinaryExpression",i="ReferenceIdentifier",a="CallExpression";function f(e){let t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=!1,l="";const r=[],o=()=>{l&&r.push(t?l:{value:l,braced:n}),l=""};for(let t=0;t<e.length;t++){const r=e[t];"["===r?(o(),n=!0):"]"===r?(o(),n=!1):l+=r}return o(),r}function p(e){return{context:f(e,!0)}}function h(e){const t={},n=f(e);if(n.length>1)t.workbookName=n[n.length-2].value,t.sheetName=n[n.length-1].value;else if(1===n.length){const e=n[0];e.braced?t.workbookName=e.value:t.sheetName=e.value}return t}const g=e=>e&&":"===e.value&&{},x=e=>e&&"range"===e.type&&{r0:e.value},d=e=>e&&e.type===l&&{r0:e.value},$=e=>e&&"range"===e.type&&{r1:e.value},y=t=>t&&t.type===e&&"!"===t.value&&{},m=e=>e&&e.type===n&&{r0:e.value},v=e=>e&&e.type===o&&{struct:e.value},E=(e,t)=>{const n=t.xlsx?h:p;return e&&"context"===e.type?n(e.value):e&&"context_quote"===e.type?n(e.value.slice(1,-1).replace(/''/g,"'")):void 0},R=e=>e&&e.type===r&&{name:e.value},w=[[d],[x,g,$],[x],[m],[E,y,d],[E,y,x,g,$],[E,y,x],[E,y,m]],N=w.concat([[R],[E,y,R],[v],[R,v],[E,y,R,v]]);function b(e,t){const n={withLocation:!1,mergeRefs:!1,allowTernary:!1,allowNamed:!0,r1c1:!1,xlsx:!1,...t},l=Fe(e,Ae,n),r=n.xlsx?{workbookName:"",sheetName:"",r0:"",r1:"",name:""}:{context:[],r0:"",r1:"",name:""};l.length&&"fx_prefix"===l[0].type&&l.shift();const o=n.allowNamed?N:w;for(let e=0;e<o.length;e++){const t={...r};if(o[e].length===l.length){const r=o[e].every(((e,r)=>{const o=e(l[r],n);return Object.assign(t,o),o}));if(r)return t}}return null}const A=/[^0-9A-Za-z._¡¤§¨ª\u00ad¯-\uffff]/;function C(e){let t="",n=0,l=0;const r=e.context||[];for(let e=r.length;e>-1;e--){const o=r[e];if(o){t=(l%2?"["+o+"]":o)+t,n+=A.test(o),l++}}return n&&(t="'"+t.replace(/'/g,"''")+"'"),t?t+"!":t}function T(e){let t="",n=0;const{workbookName:l,sheetName:r}=e;return l&&(t+="["+l+"]",n+=A.test(l)),r&&(t+=r,n+=A.test(r)),n&&(t="'"+t.replace(/'/g,"''")+"'"),t?t+"!":t}const I=(e,t,n)=>Math.min(Math.max(t,e),n),L=(e,t)=>(t?"$":"")+U(e),k=(e,t)=>(t?"$":"")+String(e+1),O=String.fromCharCode;function _(e){const t=e||"",n=t.length;let l=0;if(n>2){const e=t.charCodeAt(n-3);l+=676*(1+e-(e>95?32:0)-65)}if(n>1){const e=t.charCodeAt(n-2);l+=26*(1+e-(e>95?32:0)-65)}if(n){const e=t.charCodeAt(n-1);l+=e-(e>95?32:0)-65}return l}function U(e){return(e>=702?O(((e-702)/676-0)%26+65):"")+(e>=26?O((e/26-1)%26+65):"")+O(e%26+65)}function F(e){let{top:t,left:n,bottom:l,right:r}=e;const{$left:o,$right:u,$top:s,$bottom:c}=e,i=null==n,a=null==r,f=null==t,p=null==l;t=I(0,0|t,1048575),n=I(0,0|n,16383),!i&&!f&&a&&p?(l=t,r=n):(l=I(0,0|l,1048575),r=I(0,0|r,16383));if(0===t&&l>=1048575&&!i&&!a&&(!(o&&!i||u&&!a)||n===r)||f&&p)return L(n,o)+":"+L(r,u);return 0===n&&r>=16383&&!f&&!p&&(!(s&&!f||c&&!p)||t===l)||i&&a?k(t,s)+":"+k(l,c):i||f||a||!p?i||!f||a||p?i||f||!a||p?!i||f||a||p?r!==n||l!==t||u!==o||c!==s?L(n,o)+k(t,s)+":"+L(r,u)+k(l,c):L(n,o)+k(t,s):L(r,u)+k(t,s)+":"+k(l,c):L(n,o)+k(t,s)+":"+k(l,c):L(n,o)+k(l,c)+":"+L(r,u):L(n,o)+k(t,s)+":"+L(r,u)}function S(e){const t=/^(?=.)(\$(?=\D))?([A-Za-z]{0,3})?(\$)?([1-9][0-9]{0,6})?$/.exec(e);return t&&(t[2]||t[4])?[t[4]?(n=t[4],+n-1):null,t[2]?_(t[2]):null,!!t[3],!!t[1]]:null;var n}function M(e){let t=null,n=null,l=null,r=null,o=!1,u=!1,s=!1,c=!1;const[i,a,f]=e.split(":");if(f)return null;const p=S(i),h=a?S(a):null;if(!p||a&&!h)return null;if(null!=p[0]&&null!=p[1]?[t,n,o,u]=p:null==p[0]&&null!=p[1]?[,n,,u]=p:null!=p[0]&&null==p[1]&&([t,,o]=p),a)null!=h[0]&&null!=h[1]?[l,r,s,c]=h:null==h[0]&&null!=h[1]?[,r,,c]=h:null!=h[0]&&null==h[1]&&([l,,s]=h);else{if(null==t||null==n)return null;l=t,r=n,s=o,c=u}return null!=r&&(null==n||null!=n&&r<n)&&([n,r,u,c]=[r,n,c,u]),null!=l&&(null==t||null!=t&&l<t)&&([t,l,o,s]=[l,t,s,o]),{top:t,left:n,bottom:l,right:r,$top:o,$left:u,$bottom:s,$right:c}}function z(e){let{allowNamed:t=!0,allowTernary:n=!1,xlsx:l=!1}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const r=b(e,{allowNamed:t,allowTernary:n,xlsx:l,r1c1:!1});if(r&&(r.r0||r.name)){let e=null;return r.r0&&(e=M(r.r1?r.r0+":"+r.r1:r.r0)),r.name||e?(r.range=e,delete r.r0,delete r.r1,r):null}return null}function D(e){let{xlsx:t=!1}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const n=t?T(e):C(e);return n+(e.name?e.name:F(e.range))}function j(e){return null==e.top&&(e.top=0,e.$top=!1),null==e.bottom&&(e.bottom=1048575,e.$bottom=!1),null==e.left&&(e.left=0,e.$left=!1),null==e.right&&(e.right=16383,e.$right=!1),e}const Z=/^\[('['#@[\]]|[^'#@[\]])+\]/i,q=/^([^#@[\]:]+)/i,B={headers:1,data:2,totals:4,all:8,"this row":16,"@":16},P=function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return Object.freeze(t)},X={0:P(),1:P("headers"),2:P("data"),4:P("totals"),8:P("all"),16:P("this row"),3:P("headers","data"),6:P("data","totals")},W=function(e){let t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=Z.exec(e);if(n){const e=n[0].slice(1,-1).replace(/'(['#@[\]])/g,"$1");return[n[0],e]}return t&&(n=q.exec(e),n)?[n[0],n[0]]:null};function H(e){const t=[];let n,l,r=0,o=e,u=0;if(!(n=/^(\[\s*)/.exec(o)))return null;if(l=/^\[#([a-z ]+)\]/i.exec(o)){const e=l[1].toLowerCase();if(r+=l[0].length,!B[e])return null;u|=B[e]}else if(l=W(o,!1))r+=l[0].length,t.push(l[1].trim());else{let l=!0;for(o=o.slice(n[1].length),r+=n[1].length;l&&(n=/^\[#([a-z ]+)\](\s*,\s*)?/i.exec(o));){const e=n[1].toLowerCase();if(!B[e])return null;u|=B[e],o=o.slice(n[0].length),r+=n[0].length,l=!!n[2]}if(l&&(n=/^@/.exec(o))&&(u|=B["@"],o=o.slice(1),r+=1,l="]"!==o[0]),!(u in X))return null;const s=l?W(e.slice(r)):null;if(s){if(r+=s[0].length,t.push(s[1].trim()),o=e.slice(r),":"===o[0]){o=o.slice(1),r++;const e=W(o);if(!e)return null;r+=e[0].length,t.push(e[1].trim())}l=!1}for(;" "===e[r];)r++;if(l||"]"!==e[r])return null;r++}const s=X[u];return{columns:t,sections:s?s.concat():s,length:r,token:e.slice(0,r)}}function Y(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{xlsx:!1};const n=b(e,t);if(n&&n.struct){const e=H(n.struct);if(e&&e.length===n.struct.length)return t.xlsx?{workbookName:n.workbookName,sheetName:n.sheetName,table:n.name,columns:e.columns,sections:e.sections}:{context:n.context,table:n.name,columns:e.columns,sections:e.sections}}return null}function G(e){return e.replace(/([[\]#'@])/g,"'$1")}function K(e){return!/^[a-zA-Z0-9\u00a1-\uffff]+$/.test(e)}function V(e){return e[0].toUpperCase()+e.slice(1).toLowerCase()}function Q(e){let{xlsx:t=!1}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t?T(e):C(e);e.table&&(n+=e.table);const l=e.columns?.length??0,r=e.sections?.length??0;if(1!==r||l)if(r||1!==l){n+="[";const t=1===r&&"this row"===e.sections[0].toLowerCase();t?n+="@":r&&(n+=e.sections.map((e=>`[#${V(e)}]`)).join(","),l&&(n+=",")),t&&1===e.columns.length&&!K(e.columns[0])?n+=G(e.columns[0]):l&&(n+=e.columns.slice(0,2).map((e=>`[${G(e)}]`)).join(":")),n+="]"}else n+=`[${G(e.columns[0])}]`;else n+=`[#${V(e.sections[0])}]`;return n}const J=/^(?!!)(\[(?:[^\]])+\])?([0-9A-Za-z._¡¤§¨ª\u00ad¯-\uffff]+)?(?=!)/,ee=/^'(?:''|[^'])*('|$)(?=!)/,te="\\$?[A-Z]{1,3}\\$?[1-9][0-9]{0,6}",ne="\\$?[A-Z]{1,3}",le="\\$?[1-9][0-9]{0,6}",re="(?![a-z0-9_\\u00a1-\\uffff])",oe=new RegExp(`^${ne}:${ne}${re}`,"i"),ue=new RegExp(`^${le}:${le}${re}`,"i"),se=new RegExp(`^${te}${re}`,"i"),ce=new RegExp(`^((${ne}|${le}):${te}|${te}:(${ne}|${le}))(?![\\w($.])`,"i"),ie="(?:R(?:\\[[+-]?\\d+\\]|[1-9][0-9]{0,6})?)",ae="(?:C(?:\\[[+-]?\\d+\\]|[1-9][0-9]{0,4})?)",fe=new RegExp(`^${ae}(:${ae})?${re}`,"i"),pe=new RegExp(`^${ie}(:${ie})?${re}`,"i"),he=new RegExp(`^(?:(?=[RC])${ie}${ae})${re}`,"i"),ge=new RegExp(`^(${ie}${ae}(:${ae}|:${ie})(?![[\\d])|(${ie}|${ae})(:${ie}${ae}))${re}`,"i"),xe=/^[a-zA-Z\\_\u00a1-\uffff][a-zA-Z0-9\\_.?\u00a1-\uffff]{0,254}/i;function de(e,t){return n=>{const l=t.exec(n);if(l)return{type:e,value:l[0]}}}function $e(e){const t=xe.exec(e);if(t){const e=t[0].toLowerCase();return"r"===e||"c"===e?null:{type:r,value:t[0]}}}const ye=/^'(?:[^[\]]+?)?(?:\[(.+?)\])?(?:[^[\]]+?)'$/,me=/^'\[(.+?)\]'$/;function ve(e,t){const n=ee.exec(e);if(n){const e=n[0];if(t.xlsx&&me.test(e)||ye.test(e))return{type:"context_quote",value:e}}const l=J.exec(e);if(l){const[,e,n]=l;if(e&&n||n||e&&!n&&t.xlsx)return{type:"context",value:l[0]}}}function Ee(e){const t=H(e);if(t){let n=t.length;for(;" "===e[n];)n++;if("!"!==e[n])return{type:o,value:t.token}}return null}const Re=/([RC])(\[?)(-?\d+)/gi,we=/(\d+|[a-zA-Z]+)/gi;function Ne(e,t){let r,o;if(t.r1c1){if(t.allowTernary&&(r=ge.exec(e))?o={type:l,value:r[0]}:(r=he.exec(e))?o={type:"range",value:r[0]}:((r=pe.exec(e))||(r=fe.exec(e)))&&(o={type:n,value:r[0]}),o){for(Re.lastIndex=0;null!==(r=Re.exec(o.value));){const e=("R"===r[1]?1048575:16383)+(r[2]?0:1),t=parseInt(r[3],10);if(t>e||t<-e)return null}return o}}else if(t.allowTernary&&(r=ce.exec(e))?o={type:l,value:r[0]}:(r=oe.exec(e))||(r=ue.exec(e))?o={type:n,value:r[0]}:(r=se.exec(e))&&(o={type:"range",value:r[0]}),o){for(we.lastIndex=0;null!==(r=we.exec(o.value));)if(/^\d/.test(r[1])){if(parseInt(r[1],10)-1>1048575)return null}else if(_(r[1])>16383)return null;return o}}const be=[de(t,/^#(NAME\?|FIELD!|CALC!|VALUE!|REF!|DIV\/0!|NULL!|NUM!|N\/A|GETTING_DATA\b|SPILL!|UNKNOWN!|FIELD\b|CALC\b|SYNTAX\?|ERROR!|CONNECT!|BLOCKED!|EXTERNAL!)/i),de(e,/^(<=|>=|<>|[-+/*^%&<>=]|[{},;]|[()]|@|:|!|#)/),de("func",/^[A-Z_]+[A-Z\d_.]*(?=\()/i),de("bool",/^(TRUE|FALSE)\b/i),de("newline",/^\n+/),de("whitespace",/^[ \f\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/),de("string",/^"(?:""|[^"])*("|$)/),ve,Ne,Ee,de("number",/^(?:\d+(\.\d+)?(?:[eE][+-]?\d+)?|\d+)/),$e],Ae=[function(t,n){return n.r1c1?"!"===t[0]?{type:e,value:t[0]}:null:"!"===t[0]||":"===t[0]?{type:e,value:t[0]}:null},ve,Ne,Ee,$e],Ce={};function Te(e,t){if(e.length){const n=e[0];t[n]=t[n]||{},Te(e.slice(1),t[n])}else t.$=!0}[["range",":","range"],["range"],[n],[l],["context","!","range",":","range"],["context","!","range"],["context","!",n],["context","!",l],["context_quote","!","range",":","range"],["context_quote","!","range"],["context_quote","!",n],["context_quote","!",l],[r],["context","!",r],["context_quote","!",r],[o],[r,o],["context","!",r,o],["context_quote","!",r,o]].forEach((e=>Te(e.concat().reverse(),Ce)));const Ie=function(t,n,l){let r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0;const o=t[l-r];if(o){const u=o.type===e?o.value:o.type;if(u in n)return Ie(t,n[u],l,r+1)}return n.$?r:0};function Le(e){const t=[];for(let n=e.length-1;n>=0;n--){let l=e[n];const r=Ie(e,Ce,n);if(r){const t=e.slice(n-r+1,n+1);l={...l},l.value=t.map((e=>e.value)).join(""),l.loc&&t[0].loc&&(l.loc[0]=t[0].loc[0]),n-=r-1}t.unshift(l)}return t}const ke=(e,t)=>e&&e.type===t,Oe={withLocation:!1,mergeRefs:!0,allowTernary:!1,negativeNumbers:!0,r1c1:!1},_e=e=>e.type===r||"func"===e.type,Ue=t=>!ke(t,e)||"%"===t.value||"}"===t.value||")"===t.value||"#"===t.value;function Fe(t,n){let l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};const r=Object.assign({},Oe,l),{withLocation:o,mergeRefs:s,negativeNumbers:c}=r,i=[];let a=0,f=null,p=null,h=null;const g=e=>{const t=e.type===u,n=h&&h.type===u;h&&(t&&n||t&&_e(h)||n&&_e(e))?(h.value+=e.value,h.type=u,o&&(h.loc[1]=e.loc[1])):(i.push(e),h=e,"whitespace"!==e.type&&"newline"!==e.type&&(p=f,f=e))};if(/^=/.test(t)){a++,g({type:"fx_prefix",value:"=",...o?{loc:[0,1]}:{}})}for(;a<t.length;){const l=a,s=t.slice(a);let x="",d="";for(let e=0;e<n.length;e++){const t=n[e](s,r);if(t){x=t.type,d=t.value,a+=d.length;break}}x||(x=u,d=t[a],a++);const $={type:x,value:d,...o?{loc:[l,a]}:{}};if("string"===x){const e=d.length;if('""'===d);else if('"'===d||'"'!==d[e-1])$.unterminated=!0;else if('""'!==d&&'"'===d[e-2]){let t=e-1;for(;'"'===d[t];)t--;!(t+1)^(e-t+1)%2==0&&($.unterminated=!0)}}if(c&&"number"===x){const t=h;if(t&&ke(t,e)&&"-"===t.value&&(!p||ke(p,"fx_prefix")||!Ue(p))){const e=i.pop();$.value="-"+d,o&&($.loc[0]=e.loc[0]),f=p,h=i[i.length-1]}}g($)}return s?Le(i):i}function Se(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return Fe(e,be,t)}function Me(e){return!!e&&("range"===e.type||e.type===n||e.type===l)}function ze(e){return!!e&&("range"===e.type||e.type===n||e.type===l||e.type===o||e.type===r)}function De(e){return!!e&&("bool"===e.type||e.type===t||"number"===e.type||"string"===e.type)}function je(e){return!!e&&e.type===t}function Ze(e){return!!e&&("whitespace"===e.type||"newline"===e.type)}function qe(e){return!!e&&"func"===e.type}function Be(e){return!!e&&"fx_prefix"===e.type}function Pe(t){return!!t&&t.type===e}const Xe="(END)",We=["ANCHORARRAY","CHOOSE","DROP","IF","IFS","INDEX","INDIRECT","LAMBDA","LET","OFFSET","REDUCE","SINGLE","SWITCH","TAKE","XLOOKUP"],He=e=>!!e&&(e.type===i||("ErrorLiteral"===e.type||e.type===t)&&"#REF!"===e.value||e.type===c&&(":"===e.operator||" "===e.operator||","===e.operator)||e.type===a&&We.includes(e.callee.name.toUpperCase())),Ye={};let Ge,Ke,Ve,Qe=!1,Je=!1;function et(e){const t=new Error(e);throw t.source=Ke.map((e=>e.value)).join(""),t.sourceOffset=Ke.slice(0,Ve).reduce(((e,t)=>e+t.value),"").length,t}function tt(){let e,t=Ve;do{e=Ke[++t]}while(e&&(Ze(e)||Pe(e)&&"("===e.value));return(e=>{const t=(e&&e.value)+"";return!(!ze(e)&&(!Pe(e)||":"!==t&&","!==t&&t.trim())&&(!qe(e)||!We.includes(t.toUpperCase()))&&(!je(e)||"#REF!"!==t))})(e)}function nt(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;if(e&&e!==Ge.id&&et(`Expected ${e} but got ${Ge.id}`),Ze(Ke[Ve])){if(!(He(t)&&tt()))for(;Ze(Ke[Ve]);)Ve++}if(Ve>=Ke.length)return void(Ge=Ye[Xe]);const n=Ke[Ve];let l;Ve+=1,n.unterminated&&et("Encountered an unterminated token");let r=n.type;return Pe(n)?(l=Ye[n.value],l||et(`Unknown operator ${n.value}`)):Ze(n)?l=Ye["(WHITESPACE)"]:De(n)?l=Ye.Literal:ze(n)?(l=Ye[i],r=i):qe(n)?l=Ye["(FUNCTION)"]:et(`Unexpected ${n.type} token: ${n.value}`),Ge=Object.create(l),Ge.type=r,Ge.value=n.value,n.loc&&(Ge.loc=[...n.loc]),Ge}function lt(e){let t=Ge;nt(null,t);let n=t.nud();for(;e<Ge.lbp;)t=Ge,nt(null,t),n=t.led(n);return n}const rt={nud:()=>et("Invalid syntax"),led:()=>et("Missing operator")};function ot(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=Ye[e];return n?t>=n.lbp&&(n.lbp=t):(n={...rt},n.id=e,n.value=e,n.lbp=t,Ye[e]=n),n}function ut(e,t,n){const l=ot(e,t);return l.led=n||function(e){this.type=c,this.operator=this.value,delete this.value;const n=lt(t);return this.arguments=[e,n],this.loc&&(this.loc=[e.loc[0],n.loc[1]]),this},l}function st(e,t){const n=ot(e,0);return n.lbp=70,n.led=t||function(e){return this.type=s,this.operator=this.value,delete this.value,this.arguments=[e],this.loc&&(this.loc[0]=e.loc[0]),this},n}function ct(e,t){const n=ot(e);return n.nud=t||function(){this.type=s,this.operator=this.value,delete this.value;const e=lt(70);return this.arguments=[e],this.loc&&(this.loc[1]=e.loc[1]),this},n}function it(e,t){return ut(e,t,(function(n){He(n)||et(`Unexpected ${e} operator`);const l=lt(t);return He(l)||et(`Unexpected ${Ge.type} following ${this.id}`),this.type=c,this.operator=this.value.trim()?this.value:" ",delete this.value,this.arguments=[n,l],this.loc&&(this.loc=[n.loc[0],l.loc[1]]),this}))}ot(Xe),it(":",80);const at=it(",",80);it("(WHITESPACE)",80);const ft=e=>{const t=at.lbp>0;return null!=e&&(at.lbp=e?80:0),t};function pt(){let e=1;return()=>"fxg"+e++}function ht(e,t){return null==e&&null==t||e===t}function gt(e,t){if(Array.isArray(e)!==Array.isArray(t)||e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(!ht(e[n],t[n]))return!1;return!0}function xt(e,t){return!e&&!t||String(e).toLowerCase()===String(t).toLowerCase()}function dt(e,t){if((e.name||t.name)&&e.name!==t.name)return!1;if(e.columns||t.columns){if(e.table!==t.table)return!1;if(!gt(e.columns,t.columns))return!1;if(!gt(e.sections,t.sections))return!1}return!!(!e.range&&!t.range||ht(e.range.top,t.range.top)&&ht(e.range.bottom,t.range.bottom)&&ht(e.range.left,t.range.left)&&ht(e.range.right,t.range.right))&&!(!xt(e.workbookName,t.workbookName)||!xt(e.sheetName,t.sheetName))}function $t(e,t,n){return e.sheetName||(e.sheetName=t),e.workbookName||(e.workbookName=n),e}st("%"),st("#",(function(e){return He(e)||et("# expects a reference"),this.type=s,this.operator=this.value,delete this.value,this.arguments=[e],this})),ct("+"),ct("-"),ct("@"),ut("^",50),ut("*",40),ut("/",40),ut("+",30),ut("-",30),ut("&",20),ut("=",10),ut("<",10),ut(">",10),ut("<=",10),ut(">=",10),ut("<>",10),ot("Literal").nud=function(){const{type:e,value:n}=this;if(this.type="Literal",this.raw=n,"number"===e)this.value=+n;else if("bool"===e)this.value="TRUE"===n.toUpperCase();else if(e===t)this.type="ErrorLiteral",this.value=n.toUpperCase();else{if("string"!==e)throw new Error("Unsupported literal type: "+e);this.value=n.slice(1,-1).replace(/""/g,'"')}return this},ot(i).nud=function(){return this.type=i,this},ot(")"),ct("(",(function(){const e=ft(!0),t=lt(0);return nt(")",t),ft(e),t})),ot("(FUNCTION)").nud=function(){return this},ut("(",90,(function(e){"(FUNCTION)"!==e.id&&et("Cannot call a "+e.type);const t=[];let n=!1;if(")"!==Ge.id){const e=ft(!1);for(;")"!==Ge.id;)if(Ze(Ge)&&nt(),","===Ge.id)t.push(null),n=!0,nt();else{const e=lt(0);t.push(e),n=!1,","===Ge.id&&(nt(","),n=!0)}ft(e)}n&&t.push(null);const l=Ge;return delete this.value,this.type=a,this.callee={type:"Identifier",name:e.value},e.loc&&(this.callee.loc=[...e.loc]),this.arguments=t,e.loc&&(this.loc=[e.loc[0],l.loc[1]]),nt(")",this),this})),ot("}"),ot(";"),ct("{",(function(){"}"===Ge.id&&et("Unexpected empty array");let e=[],t=!1;const n=[e],l=ft(!1);for(;!t;){if(Ze(Ge)&&nt(),De(Ge))e.push(Ye.Literal.nud.call(Ge)),nt();else if(Qe&&He(Ge))e.push(Ye[i].nud.call(Ge)),nt();else if(Je&&qe(Ge)){const t=lt(0);e.push(t)}else et(`Unexpected ${Ge.type} in array: ${Ge.value}`);","===Ge.id?nt(","):";"===Ge.id?(nt(";"),e=[],n.push(e)):t=!0}const r=Ge;return nt("}"),ft(l),this.type="ArrayExpression",this.elements=n,this.loc&&(this.loc[1]=r.loc[1]),delete this.value,this}));const yt=(e,t,n)=>Math.min(Math.max(t,e),n);function mt(e,t){return t?String(e+1):e?"["+e+"]":""}function vt(e){let{r0:t,c0:n,r1:l,c1:r}=e;const{$c0:o,$c1:u,$r0:s,$r1:c}=e,i=null==t,a=null==n;let f=null==l,p=null==r;t=yt(s?0:-1048575,0|t,1048575),n=yt(o?0:-16383,0|n,16383),!i&&f&&!a&&p?(l=t,f=!1,r=n,p=!1):(l=yt(c?0:-1048575,0|l,1048575),r=yt(u?0:-16383,0|r,16383));if(0===t&&l>=1048575&&!a&&!p||i&&f){const e=mt(n,o),t=mt(r,u);return"C"+(e===t?e:e+":C"+t)}if(0===n&&r>=16383&&!i&&!f||a&&p){const e=mt(t,s),n=mt(l,c);return"R"+(e===n?e:e+":R"+n)}const h=mt(t,s),g=mt(l,c),x=mt(n,o),d=mt(r,u);return i||f||a||p?(i?"":"R"+h)+(a?"":"C"+x)+":"+(f?"":"R"+g)+(p?"":"C"+d):h!==g||x!==d?"R"+h+"C"+x+":R"+g+"C"+d:"R"+h+"C"+x}function Et(e){let t=null,n=null,l=null,r=null;const o=/^R(?:\[([+-]?\d+)\]|(\d+))?/.exec(e);o&&(o[1]?(t=parseInt(o[1],10),l=!1):o[2]?(t=parseInt(o[2],10)-1,l=!0):(t=0,l=!1),e=e.slice(o[0].length));const u=/^C(?:\[([+-]?\d+)\]|(\d+))?/.exec(e);return u&&(u[1]?(n=parseInt(u[1],10),r=!1):u[2]?(n=parseInt(u[2],10)-1,r=!0):(n=0,r=!1),e=e.slice(u[0].length)),!o&&!u||e.length?null:[t,n,l,r]}function Rt(e){let t=null;const[n,l]=e.split(":",2),r=Et(n);if(r){const[e,n,o,u]=r;if(!l)return null!=e&&null==n?{r0:e,c0:null,r1:e,c1:null,$r0:o,$c0:!1,$r1:o,$c1:!1}:null==e&&null!=n?{r0:null,c0:n,r1:null,c1:n,$r0:!1,$c0:u,$r1:!1,$c1:u}:{r0:e||0,c0:n||0,r1:e||0,c1:n||0,$r0:o||!1,$c0:u||!1,$r1:o||!1,$c1:u||!1};{const r=Et(l);if(!r)return null;{t={};const[l,s,c,i]=r;null!=e&&null!=l?(t.r0=o===c?Math.min(e,l):e,t.$r0=o,t.r1=o===c?Math.max(e,l):l,t.$r1=c):null!=e&&null==l?(t.r0=e,t.$r0=o,t.r1=null,t.$r1=o):null==e&&null!=l?(t.r0=l,t.$r0=c,t.r1=null,t.$r1=c):null==e&&null==l&&(t.r0=null,t.$r0=!1,t.r1=null,t.$r1=!1),null!=n&&null!=s?(t.c0=u===i?Math.min(n,s):n,t.$c0=u,t.c1=u===i?Math.max(n,s):s,t.$c1=i):null!=n&&null==s?(t.c0=n,t.$c0=u,t.c1=null,t.$c1=u):null==n&&null!=s?(t.c0=s,t.$c0=i,t.c1=null,t.$c1=i):null==n&&null==s&&(t.c0=null,t.$c0=!1,t.c1=null,t.$c1=!1)}}}return t}function wt(e){let{allowNamed:t=!0,allowTernary:n=!1,xlsx:l=!1}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const r=b(e,{allowNamed:t,allowTernary:n,xlsx:l,r1c1:!0});if(r&&(r.r0||r.name)){const e=r.r1?Rt(r.r0+":"+r.r1):Rt(r.r0);return r.name||e?(r.range=e,delete r.r0,delete r.r1,r):null}return null}function Nt(e){let{xlsx:t=!1}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const n=t?T(e):C(e);return n+(e.name?e.name:vt(e.range))}const bt=(e,t,n)=>null==t?null:e?t:t-n,At={withLocation:!1,mergeRefs:!1,allowTernary:!0,r1c1:!1};function Ct(e,t,n,l){let r=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],o=e;if(null!=o&&!t){if(o=n+e,o<0){if(!r)return NaN;o=l+o+1}if(o>l){if(!r)return NaN;o-=l+1}}return o}const Tt={wrapEdges:!0,mergeRefs:!0,allowTernary:!0,xlsx:!1};const It=Object.freeze({OPERATOR:e,BOOLEAN:"bool",ERROR:t,NUMBER:"number",FUNCTION:"func",NEWLINE:"newline",WHITESPACE:"whitespace",STRING:"string",CONTEXT:"context",CONTEXT_QUOTE:"context_quote",REF_RANGE:"range",REF_BEAM:n,REF_TERNARY:l,REF_NAMED:r,REF_STRUCT:o,FX_PREFIX:"fx_prefix",UNKNOWN:u}),Lt=Object.freeze({UNARY:s,BINARY:c,REFERENCE:i,LITERAL:"Literal",ERROR:"ErrorLiteral",CALL:a,ARRAY:"ArrayExpression",IDENTIFIER:"Identifier"});exports.MAX_COLS=16383,exports.MAX_ROWS=1048575,exports.addA1RangeBounds=j,exports.addTokenMeta=function(e){let{sheetName:t="",workbookName:r=""}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const s=[];let c=null;const i=pt(),a=[],f=()=>s.length+(c?1:0);return e.forEach(((e,p)=>{if(e.index=p,e.depth=f(),"("===e.value)s.push(e),e.depth=f();else if(")"===e.value){const t=s.pop();if(t){const n=i();e.groupId=n,e.depth=t.depth,t.groupId=n}else e.error=!0}else if("{"===e.value)c?e.error=!0:(c=e,e.depth=f());else if("}"===e.value){if(c){const t=i();e.groupId=t,e.depth=c.depth,c.groupId=t}else e.error=!0;c=null}else if("range"===e.type||e.type===n||e.type===l||e.type===o){const n=e.type===o?Y(e.value,{allowTernary:!0,xlsx:!0}):z(e.value,{allowTernary:!0,xlsx:!0});if(n&&(n.range||n.columns)){n.source=e.value,$t(n,t,r);const l=a.find((e=>dt(e,n)));l?e.groupId=l.groupId:(n.groupId=i(),e.groupId=n.groupId,a.push(n))}}else e.type===u&&(e.error=!0)})),e},exports.fixRanges=function e(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{addBounds:!1};if("string"==typeof t)return e(Se(t,n),n).map((e=>e.value)).join("");if(!Array.isArray(t))throw new Error("fixRanges expects an array of tokens");const{addBounds:l,r1c1:r,xlsx:u}=n;if(r)throw new Error("fixRanges does not have an R1C1 mode");let s=0;return t.map((e=>{const t={...e};e.loc&&(t.loc=[...e.loc]);let n=0;if(t.type===o){const e=Q(Y(t.value,{xlsx:u}),{xlsx:u});n=e.length-t.value.length,t.value=e}else if(Me(t)){const e=z(t.value,{xlsx:u,allowTernary:!0}),r=e.range;l&&j(r);const o=D(e,{xlsx:u});n=o.length-t.value.length,t.value=o}return s||n?(t.loc&&(t.loc[0]+=s),s+=n,t.loc&&(t.loc[1]+=s)):s+=n,t}))},exports.fromCol=_,exports.isError=je,exports.isFunction=qe,exports.isFxPrefix=Be,exports.isLiteral=De,exports.isOperator=Pe,exports.isRange=Me,exports.isReference=ze,exports.isWhitespace=Ze,exports.mergeRefTokens=Le,exports.nodeTypes=Lt,exports.parse=function(e,t){if("string"==typeof e)Ke=Se(e,{withLocation:!1,...t,mergeRefs:!0});else{if(!Array.isArray(e))throw new Error("Parse requires a string or array of tokens.");Ke=e}for(Qe=t?.permitArrayRanges,Je=t?.permitArrayCalls,Ve=0;Ze(Ke[Ve])||Be(Ke[Ve]);)Ve++;nt(),ft(!0);const n=lt(0);return nt(Xe),n},exports.parseA1Ref=z,exports.parseR1C1Ref=wt,exports.parseStructRef=Y,exports.stringifyA1Ref=D,exports.stringifyR1C1Ref=Nt,exports.stringifyStructRef=Q,exports.toCol=U,exports.tokenTypes=It,exports.tokenize=Se,exports.translateToA1=function(e,n){let l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:Tt;const r=M(n),o="string"==typeof e,u={...Tt,...l},s=o?Se(e,{withLocation:!1,mergeRefs:u.mergeRefs,xlsx:u.xlsx,allowTernary:u.allowTernary,r1c1:!0}):e;let c=0;const i={xlsx:u.xlsx,allowTernary:u.allowTernary};return s.forEach((e=>{if(Me(e)){const n=e.value,l=wt(n,i),o=l.range,s={},a=Ct(o.r0,o.$r0,r.top,1048575,u.wrapEdges),f=Ct(o.r1,o.$r1,r.top,1048575,u.wrapEdges);a>f?(s.top=f,s.$top=o.$r1,s.bottom=a,s.$bottom=o.$r0):(s.top=a,s.$top=o.$r0,s.bottom=f,s.$bottom=o.$r1);const p=Ct(o.c0,o.$c0,r.left,16383,u.wrapEdges),h=Ct(o.c1,o.$c1,r.left,16383,u.wrapEdges);p>h?(s.left=h,s.$left=o.$c1,s.right=p,s.$right=o.$c0):(s.left=p,s.$left=o.$c0,s.right=h,s.$right=o.$c1),isNaN(a)||isNaN(f)||isNaN(p)||isNaN(h)?(e.type=t,e.value="#REF!",delete e.groupId):(l.range=s,e.value=D(l,i)),e.loc&&(e.loc[0]+=c,c+=e.value.length-n.length,e.loc[1]+=c)}else c&&e.loc&&(e.loc[0]+=c,e.loc[1]+=c)})),o?s.map((e=>e.value)).join(""):s},exports.translateToR1C1=function(e,t){let{xlsx:n=!1,allowTernary:l=!0}=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};const{top:r,left:o}=M(t),u="string"==typeof e,s=u?Se(e,{...At,xlsx:n,allowTernary:l}):e;let c=0;const i={xlsx:n,allowTernary:l};return s.forEach((e=>{if(Me(e)){const t=e.value,n=z(t,i),l=n.range,u={};u.r0=bt(l.$top,l.top,r),u.r1=bt(l.$bottom,l.bottom,r),u.c0=bt(l.$left,l.left,o),u.c1=bt(l.$right,l.right,o),u.$r0=l.$top,u.$r1=l.$bottom,u.$c0=l.$left,u.$c1=l.$right,n.range=u,e.value=Nt(n,i),e.loc&&(e.loc[0]+=c,c+=e.value.length-t.length,e.loc[1]+=c)}else c&&e.loc&&(e.loc[0]+=c,e.loc[1]+=c)})),u?s.map((e=>e.value)).join(""):s};
|
|
2
2
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnguanMiLCJzb3VyY2VzIjpbXSwic291cmNlc0NvbnRlbnQiOltdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIn0=
|
package/docs/API.md
CHANGED
|
@@ -743,14 +743,15 @@ Note that if you are passing in a list of tokens that was not created using `mer
|
|
|
743
743
|
|
|
744
744
|
##### Parameters
|
|
745
745
|
|
|
746
|
-
| Name
|
|
747
|
-
|
|
|
748
|
-
| formula
|
|
749
|
-
| anchorCell
|
|
750
|
-
| [options]
|
|
751
|
-
| [options].
|
|
752
|
-
| [options].
|
|
753
|
-
| [options].
|
|
746
|
+
| Name | Type | Default | Description |
|
|
747
|
+
| ---------------------- | --------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
748
|
+
| formula | `string` \| `Array<object>` | | A string (an Excel formula) or a token list that should be adjusted. |
|
|
749
|
+
| anchorCell | `string` | | A simple string reference to an A1 cell ID (`AF123` or`$C$5`). |
|
|
750
|
+
| [options] | `object` | `{}` | The options |
|
|
751
|
+
| [options].allowTernary | `boolean` | `true` | Enables the recognition of ternary ranges in the style of `A1:A` or `A1:1`. These are supported by Google Sheets but not Excel. See: References.md. |
|
|
752
|
+
| [options].mergeRefs | `boolean` | `true` | Should ranges be treated as whole references (`Sheet1!A1:B2`) or as separate tokens for each part: (`Sheet1`,`!`,`A1`,`:`,`B2`). |
|
|
753
|
+
| [options].wrapEdges | `boolean` | `true` | Wrap out-of-bounds ranges around sheet edges rather than turning them to #REF! errors |
|
|
754
|
+
| [options].xlsx | `boolean` | `false` | Switches to the `[1]Sheet1!A1` or `[1]!name` prefix syntax form for external workbooks. See: [Prefixes.md](./Prefixes.md) |
|
|
754
755
|
|
|
755
756
|
##### Returns
|
|
756
757
|
|
|
@@ -771,12 +772,13 @@ translateToR1C1("=SUM(E10,$E$2,Sheet!$E$3)", "D10");
|
|
|
771
772
|
|
|
772
773
|
##### Parameters
|
|
773
774
|
|
|
774
|
-
| Name
|
|
775
|
-
|
|
|
776
|
-
| formula
|
|
777
|
-
| anchorCell
|
|
778
|
-
| [options]
|
|
779
|
-
| [options].
|
|
775
|
+
| Name | Type | Default | Description |
|
|
776
|
+
| ---------------------- | --------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
777
|
+
| formula | `string` \| `Array<object>` | | A string (an Excel formula) or a token list that should be adjusted. |
|
|
778
|
+
| anchorCell | `string` | | A simple string reference to an A1 cell ID (`AF123` or`$C$5`). |
|
|
779
|
+
| [options] | `object` | `{}` | The options |
|
|
780
|
+
| [options].allowTernary | `boolean` | `true` | Enables the recognition of ternary ranges in the style of `A1:A` or `A1:1`. These are supported by Google Sheets but not Excel. See: References.md. |
|
|
781
|
+
| [options].xlsx | `boolean` | `false` | Switches to the `[1]Sheet1!A1` or `[1]!name` prefix syntax form for external workbooks. See: [Prefixes.md](./Prefixes.md) |
|
|
780
782
|
|
|
781
783
|
##### Returns
|
|
782
784
|
|
package/lib/a1.js
CHANGED
|
@@ -5,6 +5,7 @@ import { stringifyPrefix, stringifyPrefixAlt } from './stringifyPrefix.js';
|
|
|
5
5
|
const clamp = (min, val, max) => Math.min(Math.max(val, min), max);
|
|
6
6
|
const toColStr = (c, a) => (a ? '$' : '') + toCol(c);
|
|
7
7
|
const toRowStr = (r, a) => (a ? '$' : '') + toRow(r);
|
|
8
|
+
const charFrom = String.fromCharCode;
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Convert a column string representation to a 0 based
|
|
@@ -51,9 +52,13 @@ export function fromCol (columnString) {
|
|
|
51
52
|
*/
|
|
52
53
|
export function toCol (columnIndex) {
|
|
53
54
|
return (
|
|
54
|
-
(columnIndex >= 702
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
(columnIndex >= 702
|
|
56
|
+
? charFrom(((((columnIndex - 702) / 676) - 0) % 26) + 65)
|
|
57
|
+
: '') +
|
|
58
|
+
(columnIndex >= 26
|
|
59
|
+
? charFrom(((((columnIndex / 26) - 1) % 26) + 65))
|
|
60
|
+
: '') +
|
|
61
|
+
charFrom((columnIndex % 26) + 65)
|
|
57
62
|
);
|
|
58
63
|
}
|
|
59
64
|
|
|
@@ -102,27 +107,31 @@ export function toA1 (range) {
|
|
|
102
107
|
right = clamp(0, right | 0, MAX_COLS);
|
|
103
108
|
}
|
|
104
109
|
// A:A
|
|
105
|
-
|
|
110
|
+
const allRows = top === 0 && bottom >= MAX_ROWS;
|
|
111
|
+
const haveAbsCol = ($left && !noLeft) || ($right && !noRight);
|
|
112
|
+
if ((allRows && !noLeft && !noRight && (!haveAbsCol || left === right)) || (noTop && noBottom)) {
|
|
106
113
|
return toColStr(left, $left) + ':' + toColStr(right, $right);
|
|
107
114
|
}
|
|
108
115
|
// 1:1
|
|
109
|
-
|
|
116
|
+
const allCols = left === 0 && right >= MAX_COLS;
|
|
117
|
+
const haveAbsRow = ($top && !noTop) || ($bottom && !noBottom);
|
|
118
|
+
if ((allCols && !noTop && !noBottom && (!haveAbsRow || top === bottom)) || (noLeft && noRight)) {
|
|
110
119
|
return toRowStr(top, $top) + ':' + toRowStr(bottom, $bottom);
|
|
111
120
|
}
|
|
112
121
|
// A1:1
|
|
113
|
-
|
|
122
|
+
if (!noLeft && !noTop && !noRight && noBottom) {
|
|
114
123
|
return toColStr(left, $left) + toRowStr(top, $top) + ':' + toColStr(right, $right);
|
|
115
124
|
}
|
|
116
125
|
// A:A1 => A1:1
|
|
117
|
-
|
|
126
|
+
if (!noLeft && noTop && !noRight && !noBottom) {
|
|
118
127
|
return toColStr(left, $left) + toRowStr(bottom, $bottom) + ':' + toColStr(right, $right);
|
|
119
128
|
}
|
|
120
129
|
// A1:A
|
|
121
|
-
|
|
130
|
+
if (!noLeft && !noTop && noRight && !noBottom) {
|
|
122
131
|
return toColStr(left, $left) + toRowStr(top, $top) + ':' + toRowStr(bottom, $bottom);
|
|
123
132
|
}
|
|
124
133
|
// A:A1 => A1:A
|
|
125
|
-
|
|
134
|
+
if (noLeft && !noTop && !noRight && !noBottom) {
|
|
126
135
|
return toColStr(right, $right) + toRowStr(top, $top) + ':' + toRowStr(bottom, $bottom);
|
|
127
136
|
}
|
|
128
137
|
// A1:A1
|
package/lib/constants.js
CHANGED
|
@@ -25,5 +25,5 @@ export const CALL = 'CallExpression';
|
|
|
25
25
|
export const ARRAY = 'ArrayExpression';
|
|
26
26
|
export const IDENTIFIER = 'Identifier';
|
|
27
27
|
|
|
28
|
-
export const MAX_COLS = 2 ** 14 - 1; // 16383
|
|
29
|
-
export const MAX_ROWS = 2 ** 20 - 1; // 1048575
|
|
28
|
+
export const MAX_COLS = (2 ** 14) - 1; // 16383
|
|
29
|
+
export const MAX_ROWS = (2 ** 20) - 1; // 1048575
|
package/lib/lexer-srefs.spec.js
CHANGED
|
@@ -315,5 +315,10 @@ test('tokenize structured references (merges on)', t => {
|
|
|
315
315
|
{ type: FX_PREFIX, value: '=' },
|
|
316
316
|
{ type: REF_STRUCT, value: '\'Sales - May2020.xlsx\'!Table1[ [#Data], [#Totals], [Surf]:[Rod] ]' }
|
|
317
317
|
]);
|
|
318
|
+
|
|
319
|
+
t.isTokens('=[myworkbook.xlsx]Sheet1!TMP8w0habhr[#All]', [
|
|
320
|
+
{ type: FX_PREFIX, value: '=' },
|
|
321
|
+
{ type: REF_STRUCT, value: '[myworkbook.xlsx]Sheet1!TMP8w0habhr[#All]' }
|
|
322
|
+
]);
|
|
318
323
|
t.end();
|
|
319
324
|
});
|
package/lib/lexerParts.js
CHANGED
|
@@ -34,16 +34,17 @@ const re_CONTEXT_QUOTE = /^'(?:''|[^'])*('|$)(?=!)/;
|
|
|
34
34
|
const rngPart = '\\$?[A-Z]{1,3}\\$?[1-9][0-9]{0,6}';
|
|
35
35
|
const colPart = '\\$?[A-Z]{1,3}';
|
|
36
36
|
const rowPart = '\\$?[1-9][0-9]{0,6}';
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
const
|
|
37
|
+
const nextNotChar = '(?![a-z0-9_\\u00a1-\\uffff])';
|
|
38
|
+
const re_A1COL = new RegExp(`^${colPart}:${colPart}${nextNotChar}`, 'i');
|
|
39
|
+
const re_A1ROW = new RegExp(`^${rowPart}:${rowPart}${nextNotChar}`, 'i');
|
|
40
|
+
const re_A1RANGE = new RegExp(`^${rngPart}${nextNotChar}`, 'i');
|
|
40
41
|
const re_A1PARTIAL = new RegExp(`^((${colPart}|${rowPart}):${rngPart}|${rngPart}:(${colPart}|${rowPart}))(?![\\w($.])`, 'i');
|
|
41
42
|
const rPart = '(?:R(?:\\[[+-]?\\d+\\]|[1-9][0-9]{0,6})?)';
|
|
42
43
|
const cPart = '(?:C(?:\\[[+-]?\\d+\\]|[1-9][0-9]{0,4})?)';
|
|
43
|
-
const re_RCCOL = new RegExp(`^${cPart}(:${cPart})
|
|
44
|
-
const re_RCROW = new RegExp(`^${rPart}(:${rPart})
|
|
45
|
-
const re_RCRANGE = new RegExp(`^(?:(?=[RC])${rPart}${cPart})`, 'i');
|
|
46
|
-
const re_RCPARTIAL = new RegExp(`^(${rPart}${cPart}(:${cPart}|:${rPart})(?![[\\d])|(${rPart}|${cPart})(:${rPart}${cPart}))
|
|
44
|
+
const re_RCCOL = new RegExp(`^${cPart}(:${cPart})?${nextNotChar}`, 'i');
|
|
45
|
+
const re_RCROW = new RegExp(`^${rPart}(:${rPart})?${nextNotChar}`, 'i');
|
|
46
|
+
const re_RCRANGE = new RegExp(`^(?:(?=[RC])${rPart}${cPart})${nextNotChar}`, 'i');
|
|
47
|
+
const re_RCPARTIAL = new RegExp(`^(${rPart}${cPart}(:${cPart}|:${rPart})(?![[\\d])|(${rPart}|${cPart})(:${rPart}${cPart}))${nextNotChar}`, 'i');
|
|
47
48
|
|
|
48
49
|
// The advertized named ranges rules are a bit off from what Excel seems to do:
|
|
49
50
|
// in the "extended range" of chars, it looks like it allows most things above
|
|
@@ -51,7 +52,7 @@ const re_RCPARTIAL = new RegExp(`^(${rPart}${cPart}(:${cPart}|:${rPart})(?![[\\d
|
|
|
51
52
|
// eslint-disable-next-line
|
|
52
53
|
// const re_NAMED = /^[a-zA-Z\\_¡¤§¨ª\u00ad¯\u00b0-\uffff][a-zA-Z0-9\\_.?¡¤§¨ª\u00ad¯\u00b0-\uffff]{0,254}/i;
|
|
53
54
|
// I've simplified to allowing everything above U+00A1:
|
|
54
|
-
const re_NAMED = /^
|
|
55
|
+
const re_NAMED = /^[a-zA-Z\\_\u00a1-\uffff][a-zA-Z0-9\\_.?\u00a1-\uffff]{0,254}/i;
|
|
55
56
|
|
|
56
57
|
function makeHandler (type, re) {
|
|
57
58
|
return str => {
|
|
@@ -62,6 +63,17 @@ function makeHandler (type, re) {
|
|
|
62
63
|
};
|
|
63
64
|
}
|
|
64
65
|
|
|
66
|
+
function lexNamed (str) {
|
|
67
|
+
const m = re_NAMED.exec(str);
|
|
68
|
+
if (m) {
|
|
69
|
+
const lc = m[0].toLowerCase();
|
|
70
|
+
if (lc === 'r' || lc === 'c') {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
return { type: REF_NAMED, value: m[0] };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
65
77
|
const re_QUOTED_VALUE = /^'(?:[^[\]]+?)?(?:\[(.+?)\])?(?:[^[\]]+?)'$/;
|
|
66
78
|
const re_QUOTED_VALUE_XLSX = /^'\[(.+?)\]'$/;
|
|
67
79
|
function lexContext (str, options) {
|
|
@@ -130,9 +142,9 @@ function lexRange (str, options) {
|
|
|
130
142
|
if (t) {
|
|
131
143
|
reRCNums.lastIndex = 0;
|
|
132
144
|
while ((m = reRCNums.exec(t.value)) !== null) {
|
|
133
|
-
const x = (m[1] === 'R' ? MAX_ROWS : MAX_COLS) + (m[2] ?
|
|
145
|
+
const x = (m[1] === 'R' ? MAX_ROWS : MAX_COLS) + (m[2] ? 0 : 1);
|
|
134
146
|
const val = parseInt(m[3], 10);
|
|
135
|
-
if (val
|
|
147
|
+
if (val > x || val < -x) {
|
|
136
148
|
return null;
|
|
137
149
|
}
|
|
138
150
|
}
|
|
@@ -192,7 +204,7 @@ export const lexers = [
|
|
|
192
204
|
lexRange,
|
|
193
205
|
lexStructured,
|
|
194
206
|
makeHandler(NUMBER, re_NUMBER),
|
|
195
|
-
|
|
207
|
+
lexNamed
|
|
196
208
|
];
|
|
197
209
|
|
|
198
210
|
export const lexersRefs = [
|
|
@@ -200,5 +212,5 @@ export const lexersRefs = [
|
|
|
200
212
|
lexContext,
|
|
201
213
|
lexRange,
|
|
202
214
|
lexStructured,
|
|
203
|
-
|
|
215
|
+
lexNamed
|
|
204
216
|
];
|
package/lib/parseRef.spec.js
CHANGED
|
@@ -21,40 +21,51 @@ test('splitPrefix', t => {
|
|
|
21
21
|
testStr('[foo][bar][baz]', false, [
|
|
22
22
|
{ value: 'foo', braced: true },
|
|
23
23
|
{ value: 'bar', braced: true },
|
|
24
|
-
{ value: 'baz', braced: true }
|
|
24
|
+
{ value: 'baz', braced: true }
|
|
25
|
+
]);
|
|
25
26
|
testStr('foo[bar][baz]', false, [
|
|
26
27
|
{ value: 'foo', braced: false },
|
|
27
28
|
{ value: 'bar', braced: true },
|
|
28
|
-
{ value: 'baz', braced: true }
|
|
29
|
+
{ value: 'baz', braced: true }
|
|
30
|
+
]);
|
|
29
31
|
testStr('[foo]bar[baz]', false, [
|
|
30
32
|
{ value: 'foo', braced: true },
|
|
31
33
|
{ value: 'bar', braced: false },
|
|
32
|
-
{ value: 'baz', braced: true }
|
|
34
|
+
{ value: 'baz', braced: true }
|
|
35
|
+
]);
|
|
33
36
|
testStr('[foo][bar]baz', false, [
|
|
34
37
|
{ value: 'foo', braced: true },
|
|
35
38
|
{ value: 'bar', braced: true },
|
|
36
|
-
{ value: 'baz', braced: false }
|
|
39
|
+
{ value: 'baz', braced: false }
|
|
40
|
+
]);
|
|
37
41
|
testStr('foo[bar]baz', false, [
|
|
38
42
|
{ value: 'foo', braced: false },
|
|
39
43
|
{ value: 'bar', braced: true },
|
|
40
|
-
{ value: 'baz', braced: false }
|
|
44
|
+
{ value: 'baz', braced: false }
|
|
45
|
+
]);
|
|
41
46
|
testStr('[foo]bar[baz]', false, [
|
|
42
47
|
{ value: 'foo', braced: true },
|
|
43
48
|
{ value: 'bar', braced: false },
|
|
44
|
-
{ value: 'baz', braced: true }
|
|
49
|
+
{ value: 'baz', braced: true }
|
|
50
|
+
]);
|
|
45
51
|
testStr('[foo]bar', false, [
|
|
46
52
|
{ value: 'foo', braced: true },
|
|
47
|
-
{ value: 'bar', braced: false }
|
|
53
|
+
{ value: 'bar', braced: false }
|
|
54
|
+
]);
|
|
48
55
|
testStr('foo[bar]', false, [
|
|
49
56
|
{ value: 'foo', braced: false },
|
|
50
|
-
{ value: 'bar', braced: true }
|
|
57
|
+
{ value: 'bar', braced: true }
|
|
58
|
+
]);
|
|
51
59
|
testStr('[foo][bar]', false, [
|
|
52
60
|
{ value: 'foo', braced: true },
|
|
53
|
-
{ value: 'bar', braced: true }
|
|
61
|
+
{ value: 'bar', braced: true }
|
|
62
|
+
]);
|
|
54
63
|
testStr('[foo]', false, [
|
|
55
|
-
{ value: 'foo', braced: true }
|
|
64
|
+
{ value: 'foo', braced: true }
|
|
65
|
+
]);
|
|
56
66
|
testStr('foo', false, [
|
|
57
|
-
{ value: 'foo', braced: false }
|
|
67
|
+
{ value: 'foo', braced: false }
|
|
68
|
+
]);
|
|
58
69
|
|
|
59
70
|
t.end();
|
|
60
71
|
});
|
package/lib/parser.spec.js
CHANGED
|
@@ -227,7 +227,8 @@ test('parse array literals', t => {
|
|
|
227
227
|
[ { type: 'Literal', value: 1234, raw: '1234' } ],
|
|
228
228
|
[ { type: 'CallExpression', callee: { type: 'Identifier', name: 'UNIQUE' }, arguments: [
|
|
229
229
|
{ type: 'ReferenceIdentifier', value: 'A:A' }
|
|
230
|
-
] } ]
|
|
230
|
+
] } ]
|
|
231
|
+
] },
|
|
231
232
|
{ permitArrayCalls: true });
|
|
232
233
|
// permitArrayCalls can be nested
|
|
233
234
|
t.isParsed('={SUM({1,2}),3}',
|
|
@@ -235,9 +236,11 @@ test('parse array literals', t => {
|
|
|
235
236
|
[ { type: 'CallExpression', callee: { type: 'Identifier', name: 'SUM' }, arguments: [
|
|
236
237
|
{ type: 'ArrayExpression', elements: [ [
|
|
237
238
|
{ type: 'Literal', value: 1, raw: '1' },
|
|
238
|
-
{ type: 'Literal', value: 2, raw: '2' }
|
|
239
|
+
{ type: 'Literal', value: 2, raw: '2' }
|
|
240
|
+
] ] }
|
|
239
241
|
] },
|
|
240
|
-
{ type: 'Literal', value: 3, raw: '3' } ]
|
|
242
|
+
{ type: 'Literal', value: 3, raw: '3' } ]
|
|
243
|
+
] },
|
|
241
244
|
{ permitArrayCalls: true });
|
|
242
245
|
t.end();
|
|
243
246
|
});
|
|
@@ -259,7 +262,8 @@ test('parse function calls', t => {
|
|
|
259
262
|
type: 'CallExpression', callee: { type: 'Identifier', name: 'FOO' },
|
|
260
263
|
arguments: [
|
|
261
264
|
{ type: 'Literal', value: 1, raw: '1' },
|
|
262
|
-
{ type: 'Literal', value: 2, raw: '2' }
|
|
265
|
+
{ type: 'Literal', value: 2, raw: '2' }
|
|
266
|
+
]
|
|
263
267
|
});
|
|
264
268
|
const args = Array(300).fill('1');
|
|
265
269
|
t.isParsed(`=FOO(${args.join(',')})`, {
|
|
@@ -270,20 +274,24 @@ test('parse function calls', t => {
|
|
|
270
274
|
type: 'CallExpression', callee: { type: 'Identifier', name: 'FOO' },
|
|
271
275
|
arguments: [
|
|
272
276
|
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
273
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
277
|
+
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
278
|
+
]
|
|
274
279
|
});
|
|
275
280
|
t.isParsed('=FOO((A1,B2))', {
|
|
276
281
|
type: 'CallExpression', callee: { type: 'Identifier', name: 'FOO' },
|
|
277
282
|
arguments: [
|
|
278
283
|
{ type: 'BinaryExpression', operator: ',', arguments: [
|
|
279
284
|
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
280
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
285
|
+
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
286
|
+
] }
|
|
287
|
+
]
|
|
281
288
|
});
|
|
282
289
|
t.isParsed('=FOO(BAR())', {
|
|
283
290
|
type: 'CallExpression', callee: { type: 'Identifier', name: 'FOO' },
|
|
284
291
|
arguments: [
|
|
285
292
|
{ type: 'CallExpression', callee: { type: 'Identifier', name: 'BAR' },
|
|
286
|
-
arguments: [] }
|
|
293
|
+
arguments: [] }
|
|
294
|
+
]
|
|
287
295
|
});
|
|
288
296
|
t.isParsed('=FOO(,)', {
|
|
289
297
|
type: 'CallExpression', callee: { type: 'Identifier', name: 'FOO' },
|
|
@@ -479,8 +487,18 @@ test('parse unary operator @', t => {
|
|
|
479
487
|
// parse binary operators
|
|
480
488
|
// FIXME: add precedence & associativity tests (2+3*4)
|
|
481
489
|
[
|
|
482
|
-
'+',
|
|
483
|
-
'
|
|
490
|
+
'+',
|
|
491
|
+
'-',
|
|
492
|
+
'^',
|
|
493
|
+
'*',
|
|
494
|
+
'/',
|
|
495
|
+
'&',
|
|
496
|
+
'=',
|
|
497
|
+
'<',
|
|
498
|
+
'>',
|
|
499
|
+
'<=',
|
|
500
|
+
'>=',
|
|
501
|
+
'<>'
|
|
484
502
|
].forEach(op => {
|
|
485
503
|
test('parse binary operator ' + op, t => {
|
|
486
504
|
t.isParsed(`1${op}2`, {
|
|
@@ -496,8 +514,10 @@ test('parse unary operator @', t => {
|
|
|
496
514
|
{ type: 'BinaryExpression', operator: op,
|
|
497
515
|
arguments: [
|
|
498
516
|
{ type: 'Literal', value: 1, raw: '1' },
|
|
499
|
-
{ type: 'Literal', value: 2, raw: '2' }
|
|
500
|
-
|
|
517
|
+
{ type: 'Literal', value: 2, raw: '2' }
|
|
518
|
+
] },
|
|
519
|
+
{ type: 'Literal', value: 3, raw: '3' }
|
|
520
|
+
]
|
|
501
521
|
});
|
|
502
522
|
t.isParsed(`"foo"${op}"bar"`, {
|
|
503
523
|
type: 'BinaryExpression', operator: op,
|
|
@@ -518,10 +538,12 @@ test('parse unary operator @', t => {
|
|
|
518
538
|
arguments: [
|
|
519
539
|
{ type: 'ArrayExpression', elements: [ [
|
|
520
540
|
{ type: 'Literal', value: 1, raw: '1' },
|
|
521
|
-
{ type: 'Literal', value: 2, raw: '2' }
|
|
541
|
+
{ type: 'Literal', value: 2, raw: '2' }
|
|
542
|
+
] ] },
|
|
522
543
|
{ type: 'ArrayExpression', elements: [ [
|
|
523
544
|
{ type: 'Literal', value: 3, raw: '3' },
|
|
524
|
-
{ type: 'Literal', value: 4, raw: '4' }
|
|
545
|
+
{ type: 'Literal', value: 4, raw: '4' }
|
|
546
|
+
] ] }
|
|
525
547
|
]
|
|
526
548
|
});
|
|
527
549
|
t.isParsed(`FOO()${op}BAR()`, {
|
|
@@ -552,22 +574,26 @@ test('parse unary operator @', t => {
|
|
|
552
574
|
type: 'BinaryExpression', operator: op,
|
|
553
575
|
arguments: [
|
|
554
576
|
{ type: 'ReferenceIdentifier', value: 'named1' },
|
|
555
|
-
{ type: 'ReferenceIdentifier', value: 'named2' }
|
|
577
|
+
{ type: 'ReferenceIdentifier', value: 'named2' }
|
|
578
|
+
] });
|
|
556
579
|
t.isParsed(`A1${op}named2`, {
|
|
557
580
|
type: 'BinaryExpression', operator: op,
|
|
558
581
|
arguments: [
|
|
559
582
|
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
560
|
-
{ type: 'ReferenceIdentifier', value: 'named2' }
|
|
583
|
+
{ type: 'ReferenceIdentifier', value: 'named2' }
|
|
584
|
+
] });
|
|
561
585
|
t.isParsed(`named1${op}B2`, {
|
|
562
586
|
type: 'BinaryExpression', operator: op,
|
|
563
587
|
arguments: [
|
|
564
588
|
{ type: 'ReferenceIdentifier', value: 'named1' },
|
|
565
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
589
|
+
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
590
|
+
] });
|
|
566
591
|
t.isParsed(`(A1)${op}(B2)`, {
|
|
567
592
|
type: 'BinaryExpression', operator: op,
|
|
568
593
|
arguments: [
|
|
569
594
|
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
570
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
595
|
+
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
596
|
+
] });
|
|
571
597
|
t.isInvalidExpr(`A1${op}0`);
|
|
572
598
|
t.isInvalidExpr(`0${op}A1`);
|
|
573
599
|
t.isInvalidExpr(`0${op}0`);
|
|
@@ -578,12 +604,14 @@ test('parse unary operator @', t => {
|
|
|
578
604
|
type: 'BinaryExpression', operator: op,
|
|
579
605
|
arguments: [
|
|
580
606
|
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
581
|
-
{ type: 'ErrorLiteral', value: '#REF!', raw: '#REF!' }
|
|
607
|
+
{ type: 'ErrorLiteral', value: '#REF!', raw: '#REF!' }
|
|
608
|
+
] });
|
|
582
609
|
t.isParsed(`#REF!${op}B2`, {
|
|
583
610
|
type: 'BinaryExpression', operator: op,
|
|
584
611
|
arguments: [
|
|
585
612
|
{ type: 'ErrorLiteral', value: '#REF!', raw: '#REF!' },
|
|
586
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
613
|
+
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
614
|
+
] });
|
|
587
615
|
t.isInvalidExpr(`A1${op}#NAME?`);
|
|
588
616
|
t.isInvalidExpr(`A1${op}#VALUE!`);
|
|
589
617
|
t.isInvalidExpr(`#NULL!${op}A1`);
|
|
@@ -595,8 +623,10 @@ test('parse unary operator @', t => {
|
|
|
595
623
|
{ type: 'BinaryExpression', operator: ',',
|
|
596
624
|
arguments: [
|
|
597
625
|
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
598
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
599
|
-
|
|
626
|
+
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
627
|
+
] },
|
|
628
|
+
{ type: 'ReferenceIdentifier', value: 'C3' }
|
|
629
|
+
] });
|
|
600
630
|
t.isParsed(`C3${op}(A1,B2)`, {
|
|
601
631
|
type: 'BinaryExpression', operator: op,
|
|
602
632
|
arguments: [
|
|
@@ -604,7 +634,8 @@ test('parse unary operator @', t => {
|
|
|
604
634
|
{ type: 'BinaryExpression', operator: ',',
|
|
605
635
|
arguments: [
|
|
606
636
|
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
607
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
637
|
+
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
638
|
+
] }
|
|
608
639
|
] });
|
|
609
640
|
// intersection ops
|
|
610
641
|
t.isParsed(`(A1 B2)${op}C3`, {
|
|
@@ -613,8 +644,10 @@ test('parse unary operator @', t => {
|
|
|
613
644
|
{ type: 'BinaryExpression', operator: ' ',
|
|
614
645
|
arguments: [
|
|
615
646
|
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
616
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
617
|
-
|
|
647
|
+
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
648
|
+
] },
|
|
649
|
+
{ type: 'ReferenceIdentifier', value: 'C3' }
|
|
650
|
+
] });
|
|
618
651
|
t.isParsed(`C3${op}(A1 B2)`, {
|
|
619
652
|
type: 'BinaryExpression', operator: op,
|
|
620
653
|
arguments: [
|
|
@@ -622,7 +655,8 @@ test('parse unary operator @', t => {
|
|
|
622
655
|
{ type: 'BinaryExpression', operator: ' ',
|
|
623
656
|
arguments: [
|
|
624
657
|
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
625
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
658
|
+
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
659
|
+
] }
|
|
626
660
|
] });
|
|
627
661
|
// join ops
|
|
628
662
|
t.isParsed(`(A1:(B2))${op}C3`, {
|
|
@@ -631,8 +665,10 @@ test('parse unary operator @', t => {
|
|
|
631
665
|
{ type: 'BinaryExpression', operator: ':',
|
|
632
666
|
arguments: [
|
|
633
667
|
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
634
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
635
|
-
|
|
668
|
+
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
669
|
+
] },
|
|
670
|
+
{ type: 'ReferenceIdentifier', value: 'C3' }
|
|
671
|
+
] });
|
|
636
672
|
t.isParsed(`C3${op}(A1:(B2))`, {
|
|
637
673
|
type: 'BinaryExpression', operator: op,
|
|
638
674
|
arguments: [
|
|
@@ -640,7 +676,8 @@ test('parse unary operator @', t => {
|
|
|
640
676
|
{ type: 'BinaryExpression', operator: ':',
|
|
641
677
|
arguments: [
|
|
642
678
|
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
643
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
679
|
+
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
680
|
+
] }
|
|
644
681
|
] });
|
|
645
682
|
// ref calls
|
|
646
683
|
([
|
|
@@ -743,33 +780,38 @@ test('position information is correct', t => {
|
|
|
743
780
|
t.isParsed(
|
|
744
781
|
'=-A1',
|
|
745
782
|
{ type: 'UnaryExpression', loc: [ 1, 4 ], operator: '-', arguments: [
|
|
746
|
-
{ type: 'ReferenceIdentifier', value: 'A1', loc: [ 2, 4 ] }
|
|
783
|
+
{ type: 'ReferenceIdentifier', value: 'A1', loc: [ 2, 4 ] }
|
|
784
|
+
] },
|
|
747
785
|
{ withLocation: true }
|
|
748
786
|
);
|
|
749
787
|
t.isParsed(
|
|
750
788
|
'=10%',
|
|
751
789
|
{ type: 'UnaryExpression', loc: [ 1, 4 ], operator: '%', arguments: [
|
|
752
|
-
{ type: 'Literal', value: 10, loc: [ 1, 3 ], raw: '10' }
|
|
790
|
+
{ type: 'Literal', value: 10, loc: [ 1, 3 ], raw: '10' }
|
|
791
|
+
] },
|
|
753
792
|
{ withLocation: true }
|
|
754
793
|
);
|
|
755
794
|
t.isParsed(
|
|
756
795
|
'=-(123)',
|
|
757
796
|
{ type: 'UnaryExpression', loc: [ 1, 6 ], operator: '-', arguments: [
|
|
758
|
-
{ type: 'Literal', value: 123, loc: [ 3, 6 ], raw: '123' }
|
|
797
|
+
{ type: 'Literal', value: 123, loc: [ 3, 6 ], raw: '123' }
|
|
798
|
+
] },
|
|
759
799
|
{ withLocation: true }
|
|
760
800
|
);
|
|
761
801
|
t.isParsed(
|
|
762
802
|
'(123+(234))',
|
|
763
803
|
{ type: 'BinaryExpression', loc: [ 1, 9 ], operator: '+', arguments: [
|
|
764
804
|
{ type: 'Literal', value: 123, loc: [ 1, 4 ], raw: '123' },
|
|
765
|
-
{ type: 'Literal', value: 234, loc: [ 6, 9 ], raw: '234' }
|
|
805
|
+
{ type: 'Literal', value: 234, loc: [ 6, 9 ], raw: '234' }
|
|
806
|
+
] },
|
|
766
807
|
{ withLocation: true }
|
|
767
808
|
);
|
|
768
809
|
t.isParsed(
|
|
769
810
|
'=(A1 B2)',
|
|
770
811
|
{ type: 'BinaryExpression', loc: [ 2, 7 ], operator: ' ', arguments: [
|
|
771
812
|
{ type: 'ReferenceIdentifier', value: 'A1', loc: [ 2, 4 ] },
|
|
772
|
-
{ type: 'ReferenceIdentifier', value: 'B2', loc: [ 5, 7 ] }
|
|
813
|
+
{ type: 'ReferenceIdentifier', value: 'B2', loc: [ 5, 7 ] }
|
|
814
|
+
] },
|
|
773
815
|
{ withLocation: true }
|
|
774
816
|
);
|
|
775
817
|
t.isParsed(
|
|
@@ -789,7 +831,8 @@ test('position information is correct', t => {
|
|
|
789
831
|
[ { type: 'Literal', value: 1, loc: [ 3, 4 ], raw: '1' },
|
|
790
832
|
{ type: 'Literal', value: 2, loc: [ 6, 7 ], raw: '2' } ],
|
|
791
833
|
[ { type: 'Literal', value: 3, loc: [ 9, 10 ], raw: '3' },
|
|
792
|
-
{ type: 'Literal', value: 4, loc: [ 12, 13 ], raw: '4' } ]
|
|
834
|
+
{ type: 'Literal', value: 4, loc: [ 12, 13 ], raw: '4' } ]
|
|
835
|
+
] },
|
|
793
836
|
{ withLocation: true }
|
|
794
837
|
);
|
|
795
838
|
t.end();
|
|
@@ -802,7 +845,9 @@ test('does not tolerate unterminated tokens', t => {
|
|
|
802
845
|
arguments: [
|
|
803
846
|
{ type: 'ArrayExpression', elements: [
|
|
804
847
|
[ { type: 'ReferenceIdentifier', value: 'A:A' },
|
|
805
|
-
{ type: 'ReferenceIdentifier', value: 'B:B' } ]
|
|
848
|
+
{ type: 'ReferenceIdentifier', value: 'B:B' } ]
|
|
849
|
+
] }
|
|
850
|
+
] },
|
|
806
851
|
{ permitArrayRanges: true });
|
|
807
852
|
// whitespace in arguments
|
|
808
853
|
t.isParsed('=A2:A5=XLOOKUP(B1,C:C, D:D)',
|
|
@@ -812,19 +857,23 @@ test('does not tolerate unterminated tokens', t => {
|
|
|
812
857
|
arguments: [
|
|
813
858
|
{ type: 'ReferenceIdentifier', value: 'B1' },
|
|
814
859
|
{ type: 'ReferenceIdentifier', value: 'C:C' },
|
|
815
|
-
{ type: 'ReferenceIdentifier', value: 'D:D' }
|
|
860
|
+
{ type: 'ReferenceIdentifier', value: 'D:D' }
|
|
861
|
+
] }
|
|
862
|
+
] },
|
|
816
863
|
{ permitArrayRanges: true });
|
|
817
864
|
// whitespace surrounding comma
|
|
818
865
|
t.isParsed('=SUM(12 , B:B)',
|
|
819
866
|
{ type: 'CallExpression', callee: { type: 'Identifier', name: 'SUM' }, arguments: [
|
|
820
867
|
{ type: 'Literal', value: 12, raw: '12' },
|
|
821
|
-
{ type: 'ReferenceIdentifier', value: 'B:B' }
|
|
868
|
+
{ type: 'ReferenceIdentifier', value: 'B:B' }
|
|
869
|
+
] },
|
|
822
870
|
{ permitArrayCalls: true });
|
|
823
871
|
// whitespace tailing operator
|
|
824
872
|
t.isParsed('=A:A= C1',
|
|
825
873
|
{ type: 'BinaryExpression', operator: '=', arguments: [
|
|
826
874
|
{ type: 'ReferenceIdentifier', value: 'A:A' },
|
|
827
|
-
{ type: 'ReferenceIdentifier', value: 'C1' }
|
|
875
|
+
{ type: 'ReferenceIdentifier', value: 'C1' }
|
|
876
|
+
] },
|
|
828
877
|
{ permitArrayCalls: true });
|
|
829
878
|
t.end();
|
|
830
879
|
});
|
|
@@ -835,7 +884,9 @@ test('parser can permit xlsx mode references', t => {
|
|
|
835
884
|
{ type: 'CallExpression', callee: { type: 'Identifier', name: 'SUM' }, arguments: [
|
|
836
885
|
{ type: 'BinaryExpression', operator: '+', arguments: [
|
|
837
886
|
{ type: 'ReferenceIdentifier', value: '[Workbook.xlsx]!A1' },
|
|
838
|
-
{ type: 'ReferenceIdentifier', value: '[Workbook.xlsx]!Table1[#Data]' }
|
|
887
|
+
{ type: 'ReferenceIdentifier', value: '[Workbook.xlsx]!Table1[#Data]' }
|
|
888
|
+
] }
|
|
889
|
+
] },
|
|
839
890
|
{ xlsx: true });
|
|
840
891
|
t.end();
|
|
841
892
|
});
|
package/lib/rc.js
CHANGED
|
@@ -47,13 +47,15 @@ export function toR1C1 (range) {
|
|
|
47
47
|
c1 = clamp($c1 ? 0 : -MAX_COLS, c1 | 0, MAX_COLS);
|
|
48
48
|
}
|
|
49
49
|
// C:C
|
|
50
|
-
|
|
50
|
+
const allRows = r0 === 0 && r1 >= MAX_ROWS;
|
|
51
|
+
if ((allRows && !nullC0 && !nullC1) || (nullR0 && nullR1)) {
|
|
51
52
|
const a = toCoord(c0, $c0);
|
|
52
53
|
const b = toCoord(c1, $c1);
|
|
53
54
|
return 'C' + (a === b ? a : a + ':C' + b);
|
|
54
55
|
}
|
|
55
56
|
// R:R
|
|
56
|
-
|
|
57
|
+
const allCols = c0 === 0 && c1 >= MAX_COLS;
|
|
58
|
+
if ((allCols && !nullR0 && !nullR1) || (nullC0 && nullC1)) {
|
|
57
59
|
const a = toCoord(r0, $r0);
|
|
58
60
|
const b = toCoord(r1, $r1);
|
|
59
61
|
return 'R' + (a === b ? a : a + ':R' + b);
|
package/lib/sr.spec.js
CHANGED
|
@@ -88,6 +88,13 @@ test('parse structured references', t => {
|
|
|
88
88
|
context: [ 'Sheet1' ]
|
|
89
89
|
});
|
|
90
90
|
|
|
91
|
+
t.isSREqual('[myworkbook.xlsx]Sheet1!TMP8w0habhr[#All]', {
|
|
92
|
+
columns: [],
|
|
93
|
+
table: 'TMP8w0habhr',
|
|
94
|
+
context: [ 'myworkbook.xlsx', 'Sheet1' ],
|
|
95
|
+
sections: [ 'all' ]
|
|
96
|
+
});
|
|
97
|
+
|
|
91
98
|
t.end();
|
|
92
99
|
});
|
|
93
100
|
|
|
@@ -100,7 +100,7 @@ test('translate partials from RC to A1', t => {
|
|
|
100
100
|
t.end();
|
|
101
101
|
});
|
|
102
102
|
|
|
103
|
-
test('translate
|
|
103
|
+
test('translate bounds coords from RC to A1', t => {
|
|
104
104
|
t.isR2A('=C[-1]', 'A1', '=XFD:XFD');
|
|
105
105
|
t.isR2A('=C[-2]', 'A1', '=XFC:XFC');
|
|
106
106
|
t.isR2A('=RC[16383]', 'B1', '=A1');
|
|
@@ -110,6 +110,10 @@ test('translate out of bounds coords from RC to A1', t => {
|
|
|
110
110
|
t.isR2A('=R[1048575]C', 'A2', '=A1');
|
|
111
111
|
t.isR2A('=R[1048575]C', 'A3', '=A2');
|
|
112
112
|
|
|
113
|
+
t.isR2A('=R1:R1048576', 'A1', '=$1:$1048576');
|
|
114
|
+
t.isR2A('=C1:C16384', 'A1', '=$A:$XFD');
|
|
115
|
+
t.isR2A('=R1C1:R1048576C16384', 'A1', '=$A$1:$XFD$1048576');
|
|
116
|
+
|
|
113
117
|
const f1 = '=R[-1]C[-1]';
|
|
114
118
|
t.is(translateToA1(f1, 'A1', { wrapEdges: false }), '=#REF!', f1);
|
|
115
119
|
|
|
@@ -95,11 +95,14 @@ test('translate partials from A1 to RC', t => {
|
|
|
95
95
|
t.end();
|
|
96
96
|
});
|
|
97
97
|
|
|
98
|
-
test('translate
|
|
98
|
+
test('translate boundary coords from A1 to RC', t => {
|
|
99
99
|
t.isA2R('=XFD:XFD', 'A1', '=C[16383]');
|
|
100
100
|
t.isA2R('=A1', 'B1', '=RC[-1]');
|
|
101
101
|
t.isA2R('=B1', 'C1', '=RC[-1]');
|
|
102
102
|
t.isA2R('=1048576:1048576', 'A1', '=R[1048575]');
|
|
103
|
+
t.isA2R('=$1:$1048576', 'A1', '=R1:R1048576');
|
|
104
|
+
t.isA2R('=$A:$XFD', 'A1', '=C1:C16384');
|
|
105
|
+
t.isA2R('=$A$1:$XFD$1048576', 'A1', '=R1C1:R1048576C16384');
|
|
103
106
|
t.isA2R('=A1', 'A2', '=R[-1]C');
|
|
104
107
|
t.isA2R('=A2', 'A3', '=R[-1]C');
|
|
105
108
|
t.end();
|
package/lib/translate.js
CHANGED
|
@@ -34,18 +34,19 @@ const settings = {
|
|
|
34
34
|
* @param {string} anchorCell A simple string reference to an A1 cell ID (`AF123` or`$C$5`).
|
|
35
35
|
* @param {Object} [options={}] The options
|
|
36
36
|
* @param {boolean} [options.xlsx=false] Switches to the `[1]Sheet1!A1` or `[1]!name` prefix syntax form for external workbooks. See: [Prefixes.md](./Prefixes.md)
|
|
37
|
+
* @param {boolean} [options.allowTernary=true] Enables the recognition of ternary ranges in the style of `A1:A` or `A1:1`. These are supported by Google Sheets but not Excel. See: References.md.
|
|
37
38
|
* @return {(string | Array<Object>)} A formula string or token list (depending on which was input)
|
|
38
39
|
*/
|
|
39
|
-
export function translateToR1C1 (fx, anchorCell, { xlsx = false } = {}) {
|
|
40
|
+
export function translateToR1C1 (fx, anchorCell, { xlsx = false, allowTernary = true } = {}) {
|
|
40
41
|
const { top, left } = fromA1(anchorCell);
|
|
41
42
|
const isString = typeof fx === 'string';
|
|
42
43
|
|
|
43
44
|
const tokens = isString
|
|
44
|
-
? tokenize(fx, { ...settings, xlsx })
|
|
45
|
+
? tokenize(fx, { ...settings, xlsx, allowTernary })
|
|
45
46
|
: fx;
|
|
46
47
|
|
|
47
48
|
let offsetSkew = 0;
|
|
48
|
-
const refOpts = { xlsx, allowTernary
|
|
49
|
+
const refOpts = { xlsx, allowTernary };
|
|
49
50
|
tokens.forEach(token => {
|
|
50
51
|
if (isRange(token)) {
|
|
51
52
|
const tokenValue = token.value;
|
|
@@ -108,6 +109,7 @@ function toFixed (val, abs, base, max, wrapEdges = true) {
|
|
|
108
109
|
const defaultOptions = {
|
|
109
110
|
wrapEdges: true,
|
|
110
111
|
mergeRefs: true,
|
|
112
|
+
allowTernary: true,
|
|
111
113
|
xlsx: false
|
|
112
114
|
};
|
|
113
115
|
|
|
@@ -148,6 +150,7 @@ const defaultOptions = {
|
|
|
148
150
|
* @param {boolean} [options.wrapEdges=true] Wrap out-of-bounds ranges around sheet edges rather than turning them to #REF! errors
|
|
149
151
|
* @param {boolean} [options.mergeRefs=true] Should ranges be treated as whole references (`Sheet1!A1:B2`) or as separate tokens for each part: (`Sheet1`,`!`,`A1`,`:`,`B2`).
|
|
150
152
|
* @param {boolean} [options.xlsx=false] Switches to the `[1]Sheet1!A1` or `[1]!name` prefix syntax form for external workbooks. See: [Prefixes.md](./Prefixes.md)
|
|
153
|
+
* @param {boolean} [options.allowTernary=true] Enables the recognition of ternary ranges in the style of `A1:A` or `A1:1`. These are supported by Google Sheets but not Excel. See: References.md.
|
|
151
154
|
* @return {(string | Array<Object>)} A formula string or token list (depending on which was input)
|
|
152
155
|
*/
|
|
153
156
|
export function translateToA1 (formula, anchorCell, options = defaultOptions) {
|
|
@@ -160,13 +163,13 @@ export function translateToA1 (formula, anchorCell, options = defaultOptions) {
|
|
|
160
163
|
withLocation: false,
|
|
161
164
|
mergeRefs: opts.mergeRefs,
|
|
162
165
|
xlsx: opts.xlsx,
|
|
163
|
-
allowTernary:
|
|
166
|
+
allowTernary: opts.allowTernary,
|
|
164
167
|
r1c1: true
|
|
165
168
|
})
|
|
166
169
|
: formula;
|
|
167
170
|
|
|
168
171
|
let offsetSkew = 0;
|
|
169
|
-
const refOpts = { xlsx: opts.xlsx, allowTernary:
|
|
172
|
+
const refOpts = { xlsx: opts.xlsx, allowTernary: opts.allowTernary };
|
|
170
173
|
tokens.forEach(token => {
|
|
171
174
|
if (isRange(token)) {
|
|
172
175
|
const tokenValue = token.value;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { test, Test } from 'tape';
|
|
2
|
+
import { translateToR1C1, translateToA1 } from './translate.js';
|
|
3
|
+
|
|
4
|
+
Test.prototype.okayRoundTrip = function roundTrip (expr, anchor, options) {
|
|
5
|
+
const rc = translateToR1C1(expr, anchor, options);
|
|
6
|
+
const a1 = translateToA1(rc, anchor, options);
|
|
7
|
+
this.is(a1, expr, 'Round trip: ' + expr);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
test('translate absolute cells from A1 to RC', t => {
|
|
11
|
+
t.okayRoundTrip('=Sheet1!$1:$1048576', 'A1');
|
|
12
|
+
t.okayRoundTrip('=D$1:$BJ$1048576', 'A1');
|
|
13
|
+
t.okayRoundTrip('=VLOOKUP(C7,Röðun,4,0)', 'A1');
|
|
14
|
+
t.okayRoundTrip('=COUNTIF(B$1442:B$1048576,$G1442)', 'A1');
|
|
15
|
+
t.okayRoundTrip('=IF(p2m<=D5,10,0)*scene_spend', 'A1');
|
|
16
|
+
t.okayRoundTrip('=(kwh_used_daily*kwhbtu*co2btu)/1000000', 'A1');
|
|
17
|
+
t.okayRoundTrip('=NOPLATT1+g1_+ROIC1+WACC+G1+g1_+G130+ROIC2+WACC+g2_+WACC+N', 'A1');
|
|
18
|
+
// FIXME: translate needs to be be able to specify allowTernary=false
|
|
19
|
+
t.okayRoundTrip('=foo:C3:D4', 'A1', { allowTernary: false });
|
|
20
|
+
t.end();
|
|
21
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@borgar/fx",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.5.0",
|
|
4
4
|
"description": "Utilities for working with Excel formulas",
|
|
5
5
|
"main": "dist/fx.js",
|
|
6
6
|
"types": "dist/fx.d.ts",
|
|
@@ -41,19 +41,19 @@
|
|
|
41
41
|
"author": "Borgar Þorsteinsson <borgar@borgar.net> (http://borgar.net/)",
|
|
42
42
|
"license": "MIT",
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@babel/core": "~7.
|
|
44
|
+
"@babel/core": "~7.23.0",
|
|
45
45
|
"@babel/eslint-parser": "~7.22.15",
|
|
46
|
-
"@babel/preset-env": "~7.22.
|
|
46
|
+
"@babel/preset-env": "~7.22.20",
|
|
47
47
|
"@borgar/eslint-config": "~3.1.0",
|
|
48
48
|
"@borgar/jsdoc-tsmd": "~0.1.0",
|
|
49
49
|
"@rollup/plugin-babel": "~6.0.3",
|
|
50
50
|
"babel-eslint": "~10.1.0",
|
|
51
|
-
"eslint": "~8.
|
|
51
|
+
"eslint": "~8.50.0",
|
|
52
52
|
"jsdoc": "~4.0.2",
|
|
53
|
-
"rollup": "~3.29.
|
|
53
|
+
"rollup": "~3.29.4",
|
|
54
54
|
"rollup-plugin-minification": "~0.2.0",
|
|
55
55
|
"tap-min": "~3.0.0",
|
|
56
56
|
"typescript": "~5.2.2",
|
|
57
|
-
"tape": "~5.
|
|
57
|
+
"tape": "~5.7.0"
|
|
58
58
|
}
|
|
59
59
|
}
|