From ff5be2f544d18e0be42fcb13dd4db0fa4e167352 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Hatcher?= Date: Fri, 7 Nov 2025 19:41:55 +0100 Subject: [PATCH] UPDATE: Adds ACCRINT and ACCRINTM --- .../src/expressions/parser/static_analysis.rs | 4 +++ base/src/functions/financial.rs | 10 ++++++++ base/src/functions/mod.rs | 13 +++++++++- base/src/test/mod.rs | 1 + base/src/test/test_fn_accrint.rs | 23 ++++++++++++++++++ xlsx/tests/calc_tests/ACCRINT_ACCRINTM.xlsx | Bin 0 -> 10254 bytes 6 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 base/src/test/test_fn_accrint.rs create mode 100644 xlsx/tests/calc_tests/ACCRINT_ACCRINTM.xlsx diff --git a/base/src/expressions/parser/static_analysis.rs b/base/src/expressions/parser/static_analysis.rs index 6253d82..97840c2 100644 --- a/base/src/expressions/parser/static_analysis.rs +++ b/base/src/expressions/parser/static_analysis.rs @@ -876,6 +876,8 @@ fn get_function_args_signature(kind: &Function, arg_count: usize) -> Vec args_signature_scalars(arg_count, 0, 1), Function::Cell => args_signature_scalars(arg_count, 1, 1), Function::Info => args_signature_scalars(arg_count, 1, 1), + Function::Accrint => args_signature_scalars(arg_count, 6, 2), + Function::Accrintm => args_signature_scalars(arg_count, 4, 1), } } @@ -1139,5 +1141,7 @@ fn static_analysis_on_function(kind: &Function, args: &[Node]) -> StaticResult { Function::Sheets => scalar_arguments(args), Function::Cell => scalar_arguments(args), Function::Info => scalar_arguments(args), + Function::Accrint => scalar_arguments(args), + Function::Accrintm => scalar_arguments(args), } } diff --git a/base/src/functions/financial.rs b/base/src/functions/financial.rs index 8e11ee4..39990b7 100644 --- a/base/src/functions/financial.rs +++ b/base/src/functions/financial.rs @@ -1830,4 +1830,14 @@ impl Model { CalcResult::Number(rate * (cost - result)) } + + // ACCRINT(issue, first_interest, settlement, rate, par, frequency, [basis], [calc_method]) + pub(crate) fn fn_accrint(&mut self, args: &[Node], cell: CellReferenceIndex) -> CalcResult { + todo!() + } + + // ACCRINTM(issue, settlement, rate, par, [basis]) + pub(crate) fn fn_accrintm(&mut self, args: &[Node], cell: CellReferenceIndex) -> CalcResult { + todo!() + } } diff --git a/base/src/functions/mod.rs b/base/src/functions/mod.rs index 53a2868..671ecb3 100644 --- a/base/src/functions/mod.rs +++ b/base/src/functions/mod.rs @@ -217,6 +217,8 @@ pub enum Function { Isoweeknum, // Financial + Accrint, + Accrintm, Cumipmt, Cumprinc, Db, @@ -313,7 +315,7 @@ pub enum Function { } impl Function { - pub fn into_iter() -> IntoIter { + pub fn into_iter() -> IntoIter { [ Function::And, Function::False, @@ -571,6 +573,8 @@ impl Function { Function::Cell, Function::Info, Function::Sheets, + Function::Accrint, + Function::Accrintm, ] .into_iter() } @@ -908,6 +912,8 @@ impl Function { "CELL" => Some(Function::Cell), "INFO" => Some(Function::Info), "SHEETS" | "_XLFN.SHEETS" => Some(Function::Sheets), + "ACCRINT" => Some(Function::Accrint), + "ACCRINTM" => Some(Function::Accrintm), _ => None, } @@ -1174,6 +1180,9 @@ impl fmt::Display for Function { Function::Cell => write!(f, "CELL"), Function::Info => write!(f, "INFO"), Function::Sheets => write!(f, "SHEETS"), + + Function::Accrint => write!(f, "ACCRINT"), + Function::Accrintm => write!(f, "ACCRINTM"), } } } @@ -1458,6 +1467,8 @@ impl Model { Function::Cell => self.fn_cell(args, cell), Function::Info => self.fn_info(args, cell), Function::Sheets => self.fn_sheets(args, cell), + Function::Accrint => self.fn_accrint(args, cell), + Function::Accrintm => self.fn_accrintm(args, cell), } } } diff --git a/base/src/test/mod.rs b/base/src/test/mod.rs index f48604f..3f59253 100644 --- a/base/src/test/mod.rs +++ b/base/src/test/mod.rs @@ -61,6 +61,7 @@ mod test_number_format; mod test_arrays; mod test_escape_quotes; mod test_extend; +mod test_fn_accrint; mod test_fn_fv; mod test_fn_round; mod test_fn_type; diff --git a/base/src/test/test_fn_accrint.rs b/base/src/test/test_fn_accrint.rs new file mode 100644 index 0000000..a33bbd5 --- /dev/null +++ b/base/src/test/test_fn_accrint.rs @@ -0,0 +1,23 @@ +#![allow(clippy::unwrap_used)] + +use crate::test::util::new_empty_model; + +#[test] +fn fn_average_accrint_simple_cases() { + let mut model = new_empty_model(); + // ACCRINT(issue, first_interest, settlement, rate, par, frequency, [basis], [calc_method]) + model._set("A1", "=ACCRINT(39508, 39691, 39569, 0.1, 1000, 2, 0)"); + model._set( + "A2", + "=ACCRINT(DATE(2008, 3, 5), 39691, 39569, 0.1, 1000, 2, 0, FALSE)", + ); + model._set( + "A3", + "=ACCRINT(DATE(2008, 4, 5), 39691, 39569, 0.1, 1000, 2, 0, TRUE)", + ); + model.evaluate(); + + assert_eq!(model._get_text("A1"), *"16.666666667"); + assert_eq!(model._get_text("A2"), *"15.555555556"); + assert_eq!(model._get_text("A3"), *"7.222222222"); +} diff --git a/xlsx/tests/calc_tests/ACCRINT_ACCRINTM.xlsx b/xlsx/tests/calc_tests/ACCRINT_ACCRINTM.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..258d35ee98d36f3c9b2e9264c567768bc2fbb296 GIT binary patch literal 10254 zcmeHtg;!MT{{GM)pdcXKT|T$0t3=5NJ~n?3_tYT z`#tA)?(Z+Sch6e;U9UiLuIjHbQkc*<&kJjJXH)yx_xCfJ#Ux7$^Ud*C8@GHo?8xF6vieM|(MxmK=W2** zuqvDt7NiH4x5lnShB+UU2Rl4bXhbnhIzF4SY(MiS*3xIwC4c9)N@j)~)6wNo)1dJI z8ZK9D+}RedSPSqKB3g9V0V9+Cn6;`o-o|CA<>vC5hn|kg1A^GH4tN_Y5-|>AQfU%3 z+Z%V$=vVL_lqq@DOjFnmpsq7w><=CK`z*0a<23|=86>@NvFBDvyTuG&`tmoiwMeTp zJ8KouGcoF5)2rn_qQajB)N)CaM9Els9r;A6_SUZoYeXZ!4_D(g^>e%)2jV; z+j_+>#1B#1t@DnlLlVAZ`iAF9@$XVx3NKl#bKLXm?hXl{_BWA2v^Z%`@2@D`YY_8Z zq(+WrU?&dX&-4Gp`CqKazr1=yqOxi?Csyd8+-=yv#ne(fj-;ZSgj_523txZv#Yd2s zcXXsnpBTw-UXTPK$@;bV-VQA+3CHXXP@k{yR75?-7ou%+s|-!Mc5p#sVQ@^9aj5v( zgX=nVHg%pMtKh-p+7`!B-dy@tad3rJ=F9Q(TAVSU4haTc5n1RHk&FPnK4sly&}9|E zl%(c_hj14}>c_9-7~#pXxy3H*ga0 zqS;;*bK`A%!STtXclEE(tLHZPz;=bxc0`hs=L2(WNwvCS+L%D}ucIgknbz9ocWGHg zDOWY^RfK*nVo66;7ZGqN;ve2c*=iXeCp1}MPG=fNrGC->df>{SP&jd?Y_(|FpDFh# z_UT?o>F&cyxwrtmn3s?S#;z5)GE~bg5bF;|iJ1u`sdDn&uov zHS%Vb=VhksTi3|>IoLZvml&?-SMhj>axcc##YTHMYpPTCvGp{6w#}GGPF=V zo9f{BkE#V8LbgCbp`57f6&t-7kd{mD1I_njx&q}c*%%}B)Vo1UGv0pU2}Rmd?(~k( z7Nkdb-?I1Tuk-?-r8UD_5bY=TCKNk9nvJa@tPM0`^CN_>eoetDC5)3ZZS4dsO!kX- zaqix@X1n)1@|-+-e}g*CDyBrQztfuv=_I3hfdA-)=Cm_OV0X&EIo#;@ymkb>FtM|& zq_*k1jL}|oaZEgJbs(KF_$*kJIz3H=W>#vtMQbTaiQ_c|^tIo4OjHTV5w^X)!Ul<+ z)M%ne3gEz>J55`T{)Gbs|gTqkL!!fjrA%H-cp1>rv8yTA9p`>049w(8-;lD-Im z2aUHoaQmo*I+%}Zq}ycq`r9Y-D}m7TeZC!9YX}Z@#M{&M6@pWxm8}$QIc2? zn94s0tZ+3mu|_%U9Uh?#@32$^=g^}dq0Da0=(OrsC9Idc&J+zV1qC5?FWMDh&8vk` zJBZBjzt295H`%eCdnXD~c1$XMG%@y!O6&`Mm_~qDauZeL+qls?>((+W9uXnfc)|we z6Ye8uAIkH9b_VSueZ~abZ)P_mndf95iRzvaw`Yr?O7-CNzbE*{uN(Zq z2v5eOJP(W4HBbPO3Uq9;V#4xdS()wsJXX(Tch@;kKf5LNA34;dj~AVc3IJ%30sut! zcl>LSb+R-wb9UnRHE{i0ZL^b>Vi%}zLJnEa$Z;+(`XcIeSx3vP2wbMJ%0A5?$C==B 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 Ycr`_odv5&PK!gcszt4XJ>3{zFf2)WJwg3PC literal 0 HcmV?d00001