Package: xlcalculator
Excel Calculatorxlcalculator is a Python library that reads MS Excel files and, to the extent
of supported functions, can translate the Excel functions into Python code and
subsequently evaluate the generated Python code. Essentially doing the Excel
calculations without the need for Excel.xlcalculator is a modernization of thekoala2library.xlcalculatorcurrently supports:Loading an Excel file into a Python compatible stateSaving Python compatible stateLoading Python compatible stateIgnore worksheetsExtracting sub-portions of a model. “focussing” on provided cell addresses
or defined namesEvaluatingIndividual cellsDefined Names (a “named cell” or range)RangesShared formulasnot an Array FormulaOperands (+, -, /, *, ==, <>, <=, >=)on cells onlySet cell valueGet cell valueParsing a dict into the Model objectCode is in examples\third_party_datastructureFunctions are at the bottom of this READMELNPython Math.log() differs from Excel LN. Currently returning
Math.log()VLOOKUP
- Exact match onlyYEARFRAC
- Basis 1, Actual/actual, is only within 3 decimal placesNot currently supported:Array Formulas or CSE Formulas (not a shared formula):https://stackoverflow.com/questions/1256359/what-is-the-difference-between-a-shared-formula-and-an-array-formulaorhttps://support.office.com/en-us/article/guidelines-and-examples-of-array-formulas-7d94a64e-3ff3-4686-9372-ecfd5caa57c7#ID0EAAEAAA=Office_2013_-_Office_2019)Functions required to complete testing as per Microsoft Office Help
website for SQRT and LNEXPDBRun testsSetup your environment:virtualenv -p 3.10 ve
ve/bin/pip install -e .[test]From the root xlcalculator directory:ve/bin/py.test -rw -s --tb=nativeOr simply usetox:toxRun ExampleFrom the examples/common_use_case directory:python use_case_01.pyAdding/Registering Excel FunctionsExcel function support can be easily added.Fundamental function support is found in the xlfunctions directory. The
functions are thematically organised in modules.Excel functions can be added by any code using thexlfunctions.xl.register()decorator. Here is a simple example:fromxlcalculator.xlfunctionsimportxl@xl.register()@xl.validate_argsdefADDONE(num:xl.Number):returnnum+1The@xl.validate_argsdecorator will ensure that the annotated arguments are
converted and validated. For example, even if you pass in a string, it is
converted to a number (in typical Excel fashion):>>>ADDONE(1):2>>>ADDONE('1'):2If you would like to contribute functions, please create a pull request. All
new functions should be accompanied by sufficient tests to cover the
functionality. Tests need to be written for both the Python implementation of
the function (tests/xlfunctions) and a comparison with Excel
(tests/xlfunctions_vs_excel).Excel number precisionExcel number precision is a complex discussion.It has been discussed in aWikipedia
page.The fundamentals come down to floating point numbers and a contention between
how they are represented in memory Vs how they are stored on disk Vs how they
are presented on screen. AMicrosoft
articleexplains the contention.This project is attempting to take care while reading numbers from the Excel
file to try and remove a variety of representation errors.Further work will be required to keep numbers in-line with Excel throughout
different transformations.From what I can determine this requires a low-level implementation of a
numeric datatype (C or C++, Cython??) to replicate its behaviour. Python
built-in numeric types don’t replicate behaviours appropriately.Unit testing Excel formulas directly from the workbook.If you are interested in unit testing formulas in your workbook, you can useFlyingKoala. An example on how can
be foundhere.TODODo not treat ranges as a granular AST node it instead as an operation “:” of
two cell references to create the range. That will make implementing
features likeA1:OFFSET(...)easy to implement.Support for alternative range evaluation: by ref (pointer), by expr (lazy
eval) and current eval mode.Pointers would allow easy implementations of functions like OFFSET().Lazy evals will allow efficient implementation of IF() since execution
of true and false expressions can be delayed until it is decided which
expression is needed.Implement array functions. It is really not that hard once a proper
RangeData class has been implemented on which one can easily act with scalar
functions.Improve testingRefactor model and evaluator to use pass-by-object-reference for values of
cells which then get “used”/referenced by ranges, defined names and formulasHandle multi-file addressesImprove integration with pyopenxl for reading and writing filesexample of
problem spaceSupported FunctionsCompatibilityFunctionxlcalculatorPyCelformulasKoalaFLOORDate and TimeFunctionxlcalculatorPyCelformulasKoalaDATEDATEDIFDATEVALUEDAYDAYSEDATEEOMONTHHOURISOWEEKNUMMINUTEMONTHNOWSECONDTIMETIMEVALUETODAYWEEKDAYYEARYEARFRACEngineeringFunctionxlcalculatorPyCelformulasKoalaBIN2DECBIN2HEXBIN2OCTDEC2BINDEC2HEXDEC2OCTHEX2BINHEX2DECHEX2OCTOCT2BINOCT2DECOCT2HEXFinancialFunctionxlcalculatorPyCelformulasKoalaIRRNPVPMTPVSLNVDBXIRRXNPVInformationFunctionxlcalculatorPyCelformulasKoalaISBLANKISERRISERRORISEVENISNAISNUMBERISODDISTEXTNALogicalFunctionxlcalculatorPyCelformulasKoalaANDFALSEIFIFERRORIFSNOTORSWITCHTRUEXORLookup and referenceFunctionxlcalculatorPyCelformulasKoalaCHOOSECOLUMNCOLUMNSHLOOKUPINDEXINDIRECTLOOKUPMATCHOFFSETROWROWSVLOOKUPMath and TrigonometryFunctionxlcalculatorPyCelformulasKoalaABSACOSACOSHACOTACOTHARABICASINASINHATANATAN2ATANHCEILINGCEILING.MATHCEILING.PRECISECOSCOSHCOTCOTHCSCCSCHDECIMALDEGREESEVENEXPFACTFACTDOUBLEFLOOR.MATHFLOOR.PRECISEGCDINTISO.CEILINGLCMLNLOGLOG10MODMROUNDODDPIPOWERRADIANSRANDRANDBETWEENROMANROUNDROUNDDOWNROUNDUPSECSECHSIGNSINSINHSQRTSQRTPISUMSUMIFSUMIFSSUMPRODUCTTANTANHTRUNCStatisticalFunctionxlcalculatorPyCelformulasKoalaAVERAGEAVERAGEAAVERAGEIFAVERAGEIFSCOUNTCOUNTACOUNTBLANKCOUNTIFCOUNTIFSLARGELINESTMAXMAXAMAXIFSMINMINAMINIFSSMALLTextFunctionxlcalculatorPyCelformulasKoalaCONCATCONCATENATEEXACTFINDLEFTLENLOWERMIDREPLACERIGHTTRIMUPPERVALUECHANGES0.5.0 (2023-02-06)Added support for Python 3.10, dropped 3.8.Upgraded requirements.txt to latest versions.yearfrac==0.4.4was incompatible with latest setuptools.openpyxlhad API changes that were addressed and tests fixed.0.4.2 (2021-05-17)Make sure that decimal rounding is only set in context and not system wide.0.4.1 (2021-05-14)Fixed cross-sheet references.0.4.0 (2021-05-13)Passignore_hiddenfromread_and_parse_archive()toparse_archive()Add Excel tests forIF().AddNOT()function.ImplementedBIN2OCT(),BIN2DEC(),BIN2HEX(),OCT2BIN(),OCT2DEC(),OCT2HEX(),DEC2BIN(),DEC2OCT(),DEC2HEX(),HEX2BIN(),HEX2OCT(),HEX2DEC().Drop Python 3.7 support.0.3.0 (2021-05-13)Add support for cross-sheet references.Make*IF()functions case insensitive to properly adhere to Excel specs.Support for Python 3.9.0.2.13 (2020-12-02)Add functions:FALSE(),TRUE(),ATAN2(),ACOS(),DEGREES(),ARCCOSH(),ASIN(),ASINH(),ATAN(),CEILING(),COS(),RADIANS(),COSH(),EXP(),EVEN(),FACT(),FACTDOUBLE(),INT(),LOG(),LOG10().RAND(),RANDBETWRRN(),SIGN(),SIN(),SQRTPI(),TAN()0.2.12 (2020-11-28)Add functions:PV(),XIRR(),ISEVEN(),ISODD(),ISNUMBER(),ISERROR(),FLOOR(),ISERR()Bugfix unary operator needed to be right associated to handle cases of
double use eg; double-negative.. –4 == 40.2.11 (2020-11-16)Add functions:DAY(),YEAR(),MONTH(),NOW(),WEEKDAY()EDATE(),EOMONTH(),DAYS(),ISOWEEKNUM(),DATEDIF()FIND(),LEFT(),LEN(),LOWER(),REPLACE(),TRIM()UPPER(),EXACT()0.2.10 (2020-10-30)Support CONCATENATEUpdate setup.py classifiers, licence and keywords0.2.9 (2020-09-26)Bugfix ModelCompiler.read_and_parse_dict() where a dict being parsed into a
Model through ModelCompiler was triggering AttributeError on calling
xlcalculator.xlfunctions.xl. It’s a leftover from moving xlfunctions into
xlcalculator. There has been a test included.0.2.8 (2020-09-22)Fix implementation ofISNA()andNA().ImpementMATCH().0.2.7 (2020-09-22)Add functions:ISBLANK(),ISNA(),ISTEXT(),NA()0.2.6 (2020-09-21)AddCOUNTIIF()andCOUNTIFS()function support.0.2.5 (2020-09-21)AddSUMIFS()support.0.2.4 (2020-09-09)Updated README with supported functions.Fix bug in ModelCompiler extract method where a defined name cell was being
overwritten with the cell from one of the terms contained within the formula.
Added a test for this.Move version of yearfrac to 0.4.4. That project has removed a dependency
on the package six.0.2.3 (2020-08-18)In-boarded xlfunctions.Bugfix COUNTA.Now supports 256 arguments.Updated README. Includes words on xlfunction.Changed licence from GPL-3 style to MIT Style.0.2.2 (2020-05-28)Make dependency resolution part of the execution.AST eval’ing takes care of depedency resolution.Provide cycle detection with reporting.Implemented a specific evaluation context. That makes cache control,
namespace customization and data encapsulation much easier.Add more tokenizer tests to increase coverage.0.2.1 (2020-05-28)Use a less intrusive way to patchopenpyxl. Instead of permanently
patching the reader to support cached formula values,mockis used to
only patch the reader while reading the workbook.This way the patches do not interfere with other packages not expecting
these new classes.0.2.0 (2020-05-28)Support for delayed node evaluation by wrapping them into expressions. The
function will eval the expression when needed.Support for native Excel data types.Enable and update Excel file based function tests that are now working
properly.Flake8 source code.0.1.0 (2020-05-25)Refactoredxlcalculatortypes to be more compact.Reimplemented evaluation engine to not generate Python code anymore, but
build a proper AST from the AST nodes. Each AST node supports aneval()function that knows how to compute a result.This removes a lot of complexities around trying to determine the evaluation
context at code creation time and encoding the context as part of the
generated code.Removal of all special function handling.Use of newxlfunctionsimplementation.Use Openpyxl to load the Excel files. This provides shared formula support
for free.0.0.1b (2020-05-03)Initial release.