diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..52c909e
Binary files /dev/null and b/.DS_Store differ
diff --git a/plugin-finance-function/.DS_Store b/plugin-finance-function/.DS_Store
new file mode 100644
index 0000000..037447d
Binary files /dev/null and b/plugin-finance-function/.DS_Store differ
diff --git a/plugin-finance-function/build.gradle b/plugin-finance-function/build.gradle
new file mode 100644
index 0000000..89632b2
--- /dev/null
+++ b/plugin-finance-function/build.gradle
@@ -0,0 +1,122 @@
+
+apply plugin: 'java'
+
+
+ext {
+ /**
+ * 项目中依赖的jar的路径
+ * 1.如果依赖的jar需要打包到zip中,放置在lib根目录下
+ * 2.如果依赖的jar仅仅是编译时需要,防止在lib下子目录下即可
+ */
+ libPath = "$projectDir/../webroot/WEB-INF/lib"
+
+ /**
+ * 是否对插件的class进行加密保护,防止反编译
+ */
+ guard = true
+
+ def pluginInfo = getPluginInfo()
+ pluginPre = "fine-plugin"
+ pluginName = pluginInfo.id
+ pluginVersion = pluginInfo.version
+
+ outputPath = "$projectDir/../webroot/WEB-INF/plugins/plugin-" + pluginName + "-1.0/classes"
+}
+
+group = 'com.fr.plugin'
+version = '10.0'
+sourceCompatibility = '8'
+
+sourceSets {
+ main {
+ java.outputDir = file(outputPath)
+ output.resourcesDir = file(outputPath)
+ }
+}
+
+ant.importBuild("encrypt.xml")
+//定义ant变量
+ant.projectDir = projectDir
+ant.references["compile.classpath"] = ant.path {
+ fileset(dir: libPath, includes: '**/*.jar')
+ fileset(dir: ".",includes:"**/*.jar" )
+}
+
+classes.dependsOn('clean')
+
+task copyFiles(type: Copy,dependsOn: 'classes'){
+ from outputPath
+ into "$projectDir/classes"
+}
+
+task preJar(type:Copy,dependsOn: guard ? 'compile_encrypt_javas' : 'compile_plain_javas'){
+ from "$projectDir/classes"
+ into "$projectDir/transform-classes"
+ include "**/*.*"
+}
+jar.dependsOn("preJar")
+
+task makeJar(type: Jar,dependsOn: preJar){
+ from fileTree(dir: "$projectDir/transform-classes")
+ baseName pluginPre
+ appendix pluginName
+ version pluginVersion
+ destinationDir = file("$buildDir/libs")
+
+ doLast(){
+ delete file("$projectDir/classes")
+ delete file("$projectDir/transform-classes")
+ }
+}
+
+task copyFile(type: Copy,dependsOn: ["makeJar"]){
+ from "$buildDir/libs"
+ from("$projectDir/lib") {
+ include "*.jar"
+ }
+ from "$projectDir/plugin.xml"
+ into file("$buildDir/temp/plugin")
+}
+
+task zip(type:Zip,dependsOn:["copyFile"]){
+ from "$buildDir/temp/plugin"
+ destinationDir file("$buildDir/install")
+ baseName pluginPre
+ appendix pluginName
+ version pluginVersion
+}
+
+//控制build时包含哪些文件,排除哪些文件
+processResources {
+// exclude everything
+// 用*.css没效果
+// exclude '**/*.css'
+// except this file
+// include 'xx.xml'
+}
+
+/*读取plugin.xml中的version*/
+def getPluginInfo(){
+ def xmlFile = file("plugin.xml")
+ if (!xmlFile.exists()) {
+ return ["id":"none", "version":"1.0.0"]
+ }
+ def plugin = new XmlParser().parse(xmlFile)
+ def version = plugin.version[0].text()
+ def id = plugin.id[0].text()
+ return ["id":id,"version":version]
+}
+
+repositories {
+ mavenLocal()
+ maven {
+ url = uri('http://mvn.finedevelop.com/repository/maven-public/')
+ }
+}
+
+dependencies {
+ //使用本地jar
+ implementation fileTree(dir: 'lib', include: ['**/*.jar'])
+ implementation fileTree(dir: libPath, include: ['**/*.jar'])
+}
+
diff --git a/plugin-finance-function/build/.DS_Store b/plugin-finance-function/build/.DS_Store
new file mode 100644
index 0000000..82221db
Binary files /dev/null and b/plugin-finance-function/build/.DS_Store differ
diff --git a/plugin-finance-function/build/install/fine-plugin-com.fr.plugin.function.finance-3.0.zip b/plugin-finance-function/build/install/fine-plugin-com.fr.plugin.function.finance-3.0.zip
new file mode 100644
index 0000000..5f0364b
Binary files /dev/null and b/plugin-finance-function/build/install/fine-plugin-com.fr.plugin.function.finance-3.0.zip differ
diff --git a/plugin-finance-function/build/libs/fine-plugin-com.fr.plugin.function.finance-3.0.jar b/plugin-finance-function/build/libs/fine-plugin-com.fr.plugin.function.finance-3.0.jar
new file mode 100644
index 0000000..4de59d7
Binary files /dev/null and b/plugin-finance-function/build/libs/fine-plugin-com.fr.plugin.function.finance-3.0.jar differ
diff --git a/plugin-finance-function/build/temp/plugin/fine-plugin-com.fr.plugin.function.finance-3.0.jar b/plugin-finance-function/build/temp/plugin/fine-plugin-com.fr.plugin.function.finance-3.0.jar
new file mode 100644
index 0000000..4de59d7
Binary files /dev/null and b/plugin-finance-function/build/temp/plugin/fine-plugin-com.fr.plugin.function.finance-3.0.jar differ
diff --git a/plugin-finance-function/build/temp/plugin/plugin.xml b/plugin-finance-function/build/temp/plugin/plugin.xml
new file mode 100644
index 0000000..5d7d19e
--- /dev/null
+++ b/plugin-finance-function/build/temp/plugin/plugin.xml
@@ -0,0 +1,85 @@
+
+ * Copyright: Copyright(c) 2013 + *
+ *+ * Company: morelap + *
+ * @Version 1.0 + * @Author Morelap + * + * + */ +public class DateUtil { + public static final long Minute_MilliSecond = 60 * 1000; + public static final long Hour_MilliSecond = Minute_MilliSecond * 60; + /** + * milliseconds of a day + */ + public static final long Day_MilliSecond = Hour_MilliSecond * 24; + /** + * milliseconds of a week + */ + public static final long Week_MilliSecond = Day_MilliSecond * 7; + /** + * milliseconds of a month + */ + public static final long Month_MilliSecond = Week_MilliSecond * 30; + /** + * yyyyMMdd + */ + public static final String Date_Default_Formate = "yyyyMMdd"; + /** + * yyyy-MM-dd HH:mm:ss 2010-05-11 17:22:26 + */ + public static final String Date_Formate_All = "yyyy-MM-dd HH:mm:ss"; + /** + * dd/MM/yyyy, hh:mm + */ + public static final String DATE_FORMATE_TRANSACTION = "dd/MM/yyyy, hh:mm"; + /** + * MM/dd HH:mm + */ + public static final String DATE_FORMATE_DAY_HOUR_MINUTE = "MM/dd HH:mm"; + /** + * HH:mm + */ + public static final String DATE_FORMATE_HOUR_MINUTE = "HH:mm"; + public static final String DATE_FORMATE_HOUR_MINUTE_SECOND = "HH:mm:ss"; + + public static SimpleDateFormat dateFormate = new SimpleDateFormat(); + + /** + * 获取当前的字符串日期 + * + * @param splite + * 格式的分割线如 - 则获取的日期时间格式如下: + * @return 返回2013-07-19 + */ + public static String getNowStringDate(String splite) { + StringBuffer format = new StringBuffer(); + if (splite == null) { + format.append(Date_Default_Formate); + } else { + format.append("yyyy").append(splite).append("MM").append(splite) + .append("dd"); + } + return (new SimpleDateFormat(format.toString())).format(new Date()); + } + + /** + * 获取当前的字符串日期时间 + * + * @param splite + * 格式的分割线如 - 则获取的日期时间格式如下: + * @return 返回2013-07-19 09:08:22 + */ + public static String getNowStringDateTime(String splite) { + StringBuffer format = new StringBuffer(); + if (splite == null) { + format.append(Date_Default_Formate); + } else { + format.append("yyyy").append(splite).append("MM").append(splite) + .append("dd").append(" HH:mm:ss"); + } + return (new SimpleDateFormat(format.toString())).format(new Date()); + } + + /** + * 获取当前的字符串期时间 + * + * @param splite + * 格式的分割线如 - 则获取的日期时间格式如下: + * @return 返回09:08:22 + */ + public static String getNowStringTime() { + StringBuffer format = new StringBuffer(DATE_FORMATE_HOUR_MINUTE_SECOND); + return (new SimpleDateFormat(format.toString())).format(new Date()); + + } + + /** + * 获取昨天的日期 + * + * @return Date + */ + public static Date getYesterdayDate() { + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.DATE, -1); + return calendar.getTime(); + } + + /** + * 获取指定日期的后面的一天 即日期+1 + * + * @param stringDate + * 格式为:2012-02-02 + * @return Date + */ + public static Date getForwardDate(String stringDate) { + int year = Integer.parseInt(stringDate.substring(0, 4)); + int month = Integer.parseInt(stringDate.substring(5, 7)); + int day = Integer.parseInt(stringDate.substring(8, 10)); + Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, year); + c.set(Calendar.MONTH, month - 1); + c.set(Calendar.DAY_OF_MONTH, day); + + c.add(Calendar.DATE, 1);// 在此日期的基础上+1 + return c.getTime(); + } + + /** + * 获取指定日期的后面的一天 即日期+1 + * + * @param stringDate + * 格式为:2012-02-02 + * @return Date + */ + public static String getForwardStringDate(String stringDate, String splite) { + int year = Integer.parseInt(stringDate.substring(0, 4)); + int month = Integer.parseInt(stringDate.substring(5, 7)); + int day = Integer.parseInt(stringDate.substring(8, 10)); + Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, year); + c.set(Calendar.MONTH, month - 1); + c.set(Calendar.DAY_OF_MONTH, day); + c.add(Calendar.DATE, 1);// 在此日期的基础上+1 + return getStringDateByDate(c.getTime(), splite); + } + + /** + * 根据传进来的日期date 和格式分割线返回一个字符串的日期 + * + * @param date + * 日期 + * @param splite + * 日期格式的分割线 如:- + * @return 2013-07-19 + */ + public static String getStringDateByDate(Date date, String splite) { + StringBuffer format = new StringBuffer(); + if (splite == null) { + format.append(Date_Default_Formate); + } else { + format.append("yyyy").append(splite).append("MM").append(splite) + .append("dd"); + } + if (date == null) { + date = new Date(); + } + return (new SimpleDateFormat(format.toString())).format(date); + } + + /** + * 根据传进来的日期stringdate 和格式分割线返回一个字符串的日期 + * + * @param stringDate + * 日期 + * @param splite + * 日期格式的分割线 如:- + * @return 2013-07-19 + */ + public static String getStringDateByStringDate(String stringDate, + String splite) { + Date date = getDateByStringTime(stringDate); + return getStringDateByDate(date, splite); + } + + /** + * 根据传进来的整数获取一个日期Date + * + * @param year + * 年 + * @param month + * 月 + * @param day + * 日 + * @return Date + */ + public static Date getDateByIntegerDate(int year, int month, int day) { + Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, year); + c.set(Calendar.MONTH, month - 1); + c.set(Calendar.DAY_OF_MONTH, day); + return c.getTime(); + } + + /** + * 根据传进来的字符串日期格式 获得一个date + * + * @param stringTime + * 格式如:2013-02-13 中间的-可以为其他字符 + * @return date + */ + public static Date getDateByStringTime(String stringTime) { + int year = Integer.parseInt(stringTime.substring(0, 4)); + int month = Integer.parseInt(stringTime.substring(5, 7)); + int day = Integer.parseInt(stringTime.substring(8, 10)); + return getDateByIntegerDate(year, month, day); + } + + /** + * 获得指定日期 在1970年到现在的天数 + * + * @param date + * @return 天数 + */ + public static long getDaysFrom1970(Date date) { + String stringTime = DateUtil.getStringDateByDate(date, "-"); + int year = Integer.parseInt(stringTime.substring(0, 4)); + int month = Integer.parseInt(stringTime.substring(5, 7)); + int day = Integer.parseInt(stringTime.substring(8, 10)); + Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, year); + c.set(Calendar.MONTH, month - 1); + c.set(Calendar.DAY_OF_MONTH, day); + return (int) (c.getTimeInMillis() / 86400000); + } + + /** + * 获得指定日期 在1970年到现在的天数 + * + * @param 年 + * 月 日 + * @return 天数 + */ + public static long getDaysFrom1970(int year, int month, int day) { + Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, year); + c.set(Calendar.MONTH, month - 1); + c.set(Calendar.DAY_OF_MONTH, day); + return (int) (c.getTimeInMillis() / 86400000); + } + + /** + * 获得指定日期 在1970年到现在的天数 + * + * @param date 格式2013-03-05 中间的-可以是其他符号 或者没有符号 + * @param hasSplite 代表中间是否有符号,默认是有的,如果为false则日期的格式为:20130305 + * @return 天数 + */ + public static long getDaysFrom1970(String stringTime,boolean hasSplite) { + int year,month,day; + if(hasSplite){ + year = Integer.parseInt(stringTime.substring(0, 4)); + month = Integer.parseInt(stringTime.substring(5, 7)); + day = Integer.parseInt(stringTime.substring(8, 10)); + }else{ + year = Integer.parseInt(stringTime.substring(0, 4)); + month = Integer.parseInt(stringTime.substring(4, 6)); + day = Integer.parseInt(stringTime.substring(6, 8)); + } + Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, year); + c.set(Calendar.MONTH, month - 1); + c.set(Calendar.DAY_OF_MONTH, day); + return (int) (c.getTimeInMillis() / 86400000); + } + /** + * 获得今年年初的第一天日期 如2013-01-01 + * + * @param splite + * 分隔符号 + * @return 2013-01-01(字符串形式) + */ + public static String getYearStartString(String splite) { + String sDate = getNowStringDate(splite); + int year = Integer.parseInt(sDate.substring(0, 4)); + String yearStart = new StringBuffer().append(year).append(splite) + .append("01").append(splite).append("01").toString(); + return yearStart; + } + + /** + * 获得今年年初的第一天日期 如2013-01-01 + * + * @return 2013-01-01日期格式 + */ + public static Date getYearStartDate() { + String sDate = getNowStringDate("-"); + int year = Integer.parseInt(sDate.substring(0, 4)); + Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, year); + c.set(Calendar.MONTH, 0); + c.set(Calendar.DAY_OF_MONTH, 1); + return c.getTime(); + } + + /** + * 获得上个周末的 字符串日期, 指星期日 + * @param splite + * 分隔符号 - + * @return String 格式:2013-06-22 + */ + public static String getLastWeekStringDate(String splite) { + String stringDate=getNowStringDate("-"); + int year = Integer.parseInt(stringDate.substring(0, 4)); + int month = Integer.parseInt(stringDate.substring(5, 7)); + int day = Integer.parseInt(stringDate.substring(8, 10)); + int sundayPlus=getSundayPlus(); + Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, year); + c.set(Calendar.MONTH, month - 1); + c.set(Calendar.DAY_OF_MONTH, day); + c.add(Calendar.DATE, -sundayPlus);// 在此日期的基础上减去sundayPlus就是上个周末的日期 + return getStringDateByDate(c.getTime(), splite); + } + + /** + * 获得上个周末的日期,date格式 + * + * @return Date + */ + public static Date getLastWeekDate() { + String stringDate=getNowStringDate("-"); + int year = Integer.parseInt(stringDate.substring(0, 4)); + int month = Integer.parseInt(stringDate.substring(5, 7)); + int day = Integer.parseInt(stringDate.substring(8, 10)); + int sundayPlus=getSundayPlus(); + Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, year); + c.set(Calendar.MONTH, month - 1); + c.set(Calendar.DAY_OF_MONTH, day); + c.add(Calendar.DATE, -sundayPlus);// 在此日期的基础上减去sundayPlus就是上个周末的日期 + return c.getTime(); + + } + + /** + * 获得上个月末的 字符串日期 + * @return String + */ + public static String getLastMonthStringDate(String splite) { + String stringDate=getNowStringDate("-"); + int year = Integer.parseInt(stringDate.substring(0, 4)); + int month = Integer.parseInt(stringDate.substring(5, 7)); + int day = Integer.parseInt(stringDate.substring(8, 10)); + int monthPlus=getMonthPlus(); + Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, year); + c.set(Calendar.MONTH, month - 1); + c.set(Calendar.DAY_OF_MONTH, day); + c.add(Calendar.DATE, -monthPlus);// 在此日期的基础上减去sundayPlus就是上个周末的日期 + return getStringDateByDate(c.getTime(), splite); + } + + /** + * 获得上个月末的日期,date格式 + * + * @return Date + */ + public static Date getLastMonthDate() { + String stringDate=getNowStringDate("-"); + int year = Integer.parseInt(stringDate.substring(0, 4)); + int month = Integer.parseInt(stringDate.substring(5, 7)); + int day = Integer.parseInt(stringDate.substring(8, 10)); + int monthPlus=getMonthPlus(); + Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, year); + c.set(Calendar.MONTH, month - 1); + c.set(Calendar.DAY_OF_MONTH, day); + c.add(Calendar.DATE, -monthPlus);// 在此日期的基础上减去sundayPlus就是上个周末的日期 + return c.getTime(); + + } + + + /** + * 获得上个季度末的 字符串日期 + * @return String 2012-03-30 + */ + public static String getLastQuarterStringDate(String splite) { + String stringDate=getNowStringDate("-"); + int year = Integer.parseInt(stringDate.substring(0, 4)); + int month = Integer.parseInt(stringDate.substring(5, 7)); + switch (month) { + case 1: + case 2: + case 3: + month=12; + year--; + break; + case 4: + case 5: + case 6: + month=3; + break; + case 7: + case 8: + case 9: + month=6; + break; + case 10: + case 11: + case 12: + month=9; + break; + default: + break; + } + Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, year); + c.set(Calendar.MONTH, month);//这里月份本来是要-1的,所以这里就相当于月份month+1, + c.set(Calendar.DAY_OF_MONTH, 1);//此时的日期刚好为month+1月份的一号 + c.add(Calendar.DATE, -1);// 在1号的基础上减去一天,就是month月末的日期 + return getStringDateByDate(c.getTime(), splite); + } + + /** + * 获得上个季度末的日期,date格式 + * @return Date + */ + public static Date getLastQuarterDate() { + String stringDate=getNowStringDate("-"); + int year = Integer.parseInt(stringDate.substring(0, 4)); + int month = Integer.parseInt(stringDate.substring(5, 7)); + switch (month) { + case 1: + case 2: + case 3: + month=12; + year--; + break; + case 4: + case 5: + case 6: + month=3; + break; + case 7: + case 8: + case 9: + month=6; + break; + case 10: + case 11: + case 12: + month=9; + break; + default: + break; + } + Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, year); + c.set(Calendar.MONTH, month);//这里月份本来是要-1的,所以这里就相当于月份month+1, + c.set(Calendar.DAY_OF_MONTH, 1);//此时的日期刚好为month+1月份的一号 + c.add(Calendar.DATE, -1);// 在1号的基础上减去一天,就是month月末的日期 + return c.getTime(); + } + /** + * 获得指定月份的,月末日期 + * @param month 月 + * @return String + */ + public static String getMonthEndStringDateByMonth(int month,String splite){ + String stringDate=getNowStringDate("-"); + int year = Integer.parseInt(stringDate.substring(0, 4)); + Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, year); + c.set(Calendar.MONTH, month);//这里月份本来是要-1的,所以这里就相当于月份month+1, + c.set(Calendar.DAY_OF_MONTH, 1);//此时的日期刚好为month+1月份的一号 + c.add(Calendar.DATE, -1);// 在1号的基础上减去一天,就是month月末的日期 + return getStringDateByDate(c.getTime(), splite); + } + + /** + * 获得当前日期与上周日相差的天数 按照外国的理解:星期日是第一天,星期一是第二天. 中国:星期一是第一天. + * + * @return int今天和上周日的相差日期 + */ + public static int getSundayPlus() { + Calendar c = Calendar.getInstance(); + // 获得今天是一周的第几天,星期日是第一天,星期二是第二天...... + int dayOfWeek = c.get(Calendar.DAY_OF_WEEK) - 1; // 因为按中国礼拜一,作为第一天所以这里减1 + if(dayOfWeek==0){ + dayOfWeek=7; + } + return dayOfWeek; + } + + /** + * 获得当前日期与上个月末日期的相差天数 + * + * @return int 今天和上月末的相差日期 + */ + public static int getMonthPlus() { + Calendar c = Calendar.getInstance(); + // 获得今天是一周的第几天,星期日是第一天,星期二是第二天...... + int dayOfMonth = c.get(Calendar.DAY_OF_MONTH); + return dayOfMonth; + } + /** + * 获得两个时间相差的时间间隔,以分钟来计算 + * @param time01 格式为:2012-02-02 08:08:20 + * @param time02 格式为:2012-02-02 08:08:20 + * @return 相差的分钟数 + */ + public static long getTwoTimeInterval(String time01,String time02){ + long t01=stringTimeToMilliseconds(time01); + long t02=stringTimeToMilliseconds(time02); + return Math.abs((t01-t02)/60000); + } + /** + * 把一个字符串日期 转换成毫秒数 + * @param time 格式为:2012-02-02 08:08:20 + * @return 毫秒数 + */ + public static long stringTimeToMilliseconds(String time){ + int year = Integer.parseInt(time.substring(0, 4)); + int month = Integer.parseInt(time.substring(5, 7)); + int day = Integer.parseInt(time.substring(8, 10)); + int hour= Integer.parseInt(time.substring(11, 13)); + int minus= Integer.parseInt(time.substring(14, 16)); + int second= Integer.parseInt(time.substring(17, 19)); + Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, year); + c.set(Calendar.MONTH, month - 1); + c.set(Calendar.DAY_OF_MONTH, day); + c.add(Calendar.HOUR_OF_DAY, hour); + c.add(Calendar.MINUTE, minus); + c.add(Calendar.SECOND, second); + return c.getTimeInMillis(); + } + // java.util.Date 是 java.sql.Date 的父类 + // java.sql.Date转为java.util.Date + // java.sql.Date date=new java.sql.Date(); + // java.util.Date d=new java.util.Date (date.getTime()); + // + + // + // java.util.Date转为java.sql.Date + // java.util.Date utilDate=new Date(); + // java.sql.Date sqlDate=new java.sql.Date(utilDate.getTime()); + +} diff --git a/plugin-finance-function/src/main/java/com/fr/plugin/FV.java b/plugin-finance-function/src/main/java/com/fr/plugin/FV.java new file mode 100644 index 0000000..c4f0b8d --- /dev/null +++ b/plugin-finance-function/src/main/java/com/fr/plugin/FV.java @@ -0,0 +1,60 @@ +package com.fr.plugin; + +import com.fr.general.GeneralUtils; +import com.fr.intelli.record.Focus; +import com.fr.intelli.record.Original; +import com.fr.plugin.context.PluginContexts; +import com.fr.record.analyzer.EnableMetrics; +import com.fr.script.AbstractFunction; +import com.fr.stable.StringUtils; +import com.fr.stable.exception.FormulaException; +import com.fr.stable.fun.Authorize; +import com.fr.third.v2.org.apache.poi.ss.formula.functions.FinanceLib; + +import java.math.BigDecimal; +@EnableMetrics +@Authorize(callSignKey = FinanceFunctionConstants.PLUGIN_ID) +public class FV extends AbstractFunction { + @Override + @Focus(id = "com.fr.plugin.function.finance", text = "Plugin-Test_Function_Finance", source = Original.PLUGIN) + public Object run(Object[] objects) throws FormulaException { + if (PluginContexts.currentContext().isAvailable()) { + return cal(objects); + } else { + return "插件未激活,请购买使用"; + } + } + + private Object cal(Object[] objects) { + //年利率 + double rate = trans(objects[0]).doubleValue(); + //贷款期数 + double nper = trans(objects[1]).doubleValue(); + //每期的付款金额 + double pmt= trans(objects[2]).doubleValue(); + //pv 可选 + double pv = 0D; + if(objects.length == 4) { + pv = trans(objects[3]).doubleValue(); + } + //type 可选 + boolean type=false; + if(objects.length == 5) { + pv = trans(objects[3]).doubleValue(); + type = trans(objects[4]).doubleValue()==1; + } + return FinanceLib.fv(rate,nper,pmt,pv,type); + } + + private static BigDecimal trans(Object ele){ + if (ele == null|| StringUtils.isBlank(ele.toString())) { + return new BigDecimal("0"); + } + try{ + String val = GeneralUtils.objectToString(ele); + return new BigDecimal(val.trim()); + }catch(Exception e){ + throw new RuntimeException(e); + } + } +} diff --git a/plugin-finance-function/src/main/java/com/fr/plugin/FinanceFinder.java b/plugin-finance-function/src/main/java/com/fr/plugin/FinanceFinder.java new file mode 100644 index 0000000..fd23f22 --- /dev/null +++ b/plugin-finance-function/src/main/java/com/fr/plugin/FinanceFinder.java @@ -0,0 +1,10 @@ +package com.fr.plugin; + +import com.fr.stable.fun.impl.AbstractLocaleFinder; + +public class FinanceFinder extends AbstractLocaleFinder { + @Override + public String find() { + return "com/fr/plugin/demo"; + } +} diff --git a/plugin-finance-function/src/main/java/com/fr/plugin/FinanceFunctionConstants.java b/plugin-finance-function/src/main/java/com/fr/plugin/FinanceFunctionConstants.java new file mode 100644 index 0000000..d94ee9b --- /dev/null +++ b/plugin-finance-function/src/main/java/com/fr/plugin/FinanceFunctionConstants.java @@ -0,0 +1,6 @@ +package com.fr.plugin; + +public class FinanceFunctionConstants { + + public static final String PLUGIN_ID = "com.fr.plugin.function.finance"; +} diff --git a/plugin-finance-function/src/main/java/com/fr/plugin/FinanceGroup.java b/plugin-finance-function/src/main/java/com/fr/plugin/FinanceGroup.java new file mode 100644 index 0000000..93eba0e --- /dev/null +++ b/plugin-finance-function/src/main/java/com/fr/plugin/FinanceGroup.java @@ -0,0 +1,29 @@ +package com.fr.plugin; + +import com.fr.stable.fun.impl.AbstractFunctionDefContainer; +import com.fr.stable.script.FunctionDef; + +public class FinanceGroup extends AbstractFunctionDefContainer { + @Override + public FunctionDef[] getFunctionDefs() { + return new FunctionDef[]{ + new FunctionDef("IPMT","基于固定利率及等额分期付款方式,返回给定期数内对投资的利息偿还额函数IPMT:参数1为每期期利率,参数2为用于计算其利息数额的期数,参数3为总期数,参数4现值pv,参数5未来值fv,参数6付款时间是在期初还是期末,前四个参数必填,后面两个选填。",IPMT.class.getName()), + new FunctionDef("PPMT","PPMT函数返回根据定期固定付款和固定利率而定的投资在已知期间内的本金偿付额:参数1为每期利率,参数2为期数,参数3为总期数,参数4现值pv,参数5为未来值fv,参数6付款时间是在期初还是期末,前四个参数必填,后面两个选填。",PPMT.class.getName()), + new FunctionDef("PMT","PMT函数根据固定付款额和固定利率计算贷款的付款额:参数1为每期利率,参数2为贷款总期数,参数3现值pv即本金,参数4为未来值fv,参数5为付款时间是在期初还是期末,前三个参数必填,后面两个选填。",PMT.class.getName()), + new FunctionDef("PV","投资的现值PV:参数1为每期利率,参数2为总期数,参数3为每期付款金额,参数4未来值fv,参数5付款时间是在期初还是期末,前三个参数必填,后面两个选填。",PV.class.getName()), + new FunctionDef("FV","计算投资价值的函数FV:参数1为利率,参数2为总期数,参数3为每期付款金额,参数4现值pv,参数5每期付款时间是在期初还是期末,前三个参数必填,后面两个选填。",FV.class.getName()), + new FunctionDef("NPV","使用贴现率和一系列未来支出(负值)和收益(正值)来计算一项投资的净现值NPV:参数1为利率,可变参数-现金流,按正确的顺序输入支出值和收益值。",NPV.class.getName()), + new FunctionDef("NPER","基于固定利率及等额分期付款方式,返回某项投资的总期数NPER:参数1为各期利率,参数2为每期付款金额,参数3为现值pv,参数4未来值fv,参数5付款时间是在期初还是期末,前三个参数必填,后面两个选填。",NPER.class.getName()), + new FunctionDef("IRR","IRR函数返回由值中的数字表示的一系列现金流的内部收益率:参数1为现金流数组,参数2为估计值,参数2为选填,如果省略guess,则假定它为0.1。",IRR.class.getName()), + new FunctionDef("XIRR","XIRR函数返回一组不一定定期发生的现金流的内部收益率:参数1为现金流数组,参数2为对应还款日期列表,参数3估计值为选填。",XIRR.class.getName()), + new FunctionDef("Rate","RATE函数返回年金每期的利率:参数1为贷款总期数,参数2为每期付款金额,参数3为付款金额的总和,参数4为未来值fv,参数5为type付款时间是在期初还是期末,参数6为预期利率,省略的话默认为0.1,前三个参数必填,后三个选填。",Rate.class.getName()), + new FunctionDef("MIRR","MIRR函数返回一系列定期现金流的修改后内部收益率,同时考虑投资的成本和现金再投资的收益率:参数1为现金流数组,参数2为资金支付利率,参数3为再投资收益率。",MIRR.class.getName()) + + }; + } + + @Override + public String getGroupName() { + return "财务函数"; + } +} diff --git a/plugin-finance-function/src/main/java/com/fr/plugin/IPMT.java b/plugin-finance-function/src/main/java/com/fr/plugin/IPMT.java new file mode 100644 index 0000000..5dbb404 --- /dev/null +++ b/plugin-finance-function/src/main/java/com/fr/plugin/IPMT.java @@ -0,0 +1,66 @@ +package com.fr.plugin; + +import com.fr.general.GeneralUtils; +import com.fr.intelli.record.Focus; +import com.fr.intelli.record.Original; +import com.fr.plugin.context.PluginContexts; +import com.fr.record.analyzer.EnableMetrics; +import com.fr.script.AbstractFunction; +import com.fr.stable.StringUtils; +import com.fr.stable.exception.FormulaException; +import com.fr.stable.fun.Authorize; +import com.fr.third.v2.org.apache.poi.ss.formula.functions.Finance; + +import java.math.BigDecimal; +@EnableMetrics +@Authorize(callSignKey = FinanceFunctionConstants.PLUGIN_ID) +public class IPMT extends AbstractFunction { + @Override + @Focus(id = "com.fr.plugin.function.finance", text = "Plugin-Test_Function_Finance", source = Original.PLUGIN) + public Object run(Object[] objects) throws FormulaException { + if (PluginContexts.currentContext().isAvailable()) { + return cal(objects); + } else { + return "插件未激活,请购买使用"; + } + + } + + private Object cal(Object[] objects) { + // 各期利率 必需 + double rate = trans(objects[0]).doubleValue(); + // 指定期数 per 必需 + int per = trans(objects[1]).intValue(); + //年金的付款总期数 必需 + int nper = trans(objects[2]).intValue(); + //pv 必需 现值即一系列未来付款当前值的总和 + double pv = trans(objects[3]).doubleValue(); + + if (objects.length == 4) { + return Finance.ipmt(rate,per,nper,pv); + }else if (objects.length == 5) { + //未来值 + double fv = trans(objects[4]).doubleValue(); + return Finance.ipmt(rate,per,nper,pv,fv); + }else if (objects.length == 6) { + double fv = trans(objects[4]).doubleValue(); + int type= trans(objects[5]).intValue(); + return Finance.ipmt(rate,per,nper,pv,fv,type); + }else { + throw new RuntimeException("输入参数有误"); + } + } + + private static BigDecimal trans(Object ele){ + if (ele == null|| StringUtils.isBlank(ele.toString())) { + return new BigDecimal("0"); + } + try{ + String val = GeneralUtils.objectToString(ele); + return new BigDecimal(val.trim()); + }catch(Exception e){ + throw new RuntimeException(e); + } + } + +} diff --git a/plugin-finance-function/src/main/java/com/fr/plugin/IRR.java b/plugin-finance-function/src/main/java/com/fr/plugin/IRR.java new file mode 100644 index 0000000..769609c --- /dev/null +++ b/plugin-finance-function/src/main/java/com/fr/plugin/IRR.java @@ -0,0 +1,196 @@ +package com.fr.plugin; /** + * @file: PACKAGE_NAME.IRR + * @desc: + * @date:2020/7/7 16:57 + * @author:yanghui + **/ + +import com.fr.general.FArray; +import com.fr.general.GeneralUtils; +import com.fr.intelli.record.Focus; +import com.fr.intelli.record.Original; +import com.fr.plugin.context.PluginContexts; +import com.fr.record.analyzer.EnableMetrics; +import com.fr.script.AbstractFunction; +import com.fr.stable.StringUtils; +import com.fr.stable.fun.Authorize; + +import java.math.BigDecimal; + +@EnableMetrics +@Authorize(callSignKey = FinanceFunctionConstants.PLUGIN_ID) +public class IRR extends AbstractFunction { + + private static final long serialVersionUID = 7634415917398642321L; + private static final String ERROR_VALUE = "#NUM!"; + + + @Override + @Focus(id = "com.fr.plugin.function.finance", text = "Plugin-Test_Function_Finance", source = Original.PLUGIN) + public Object run(Object[] args) { + + if (PluginContexts.currentContext().isAvailable()) { + return cal(args); + } else { + return "插件未激活,请购买使用"; + } + + } + + private Object cal(Object[] args) { + try{ + if(1 == args.length){ + return run( transArr( (FArray) args[0] ) ); + }else if(2 == args.length){ + return run( transArr( (FArray) args[0] ), trans( args[1] ) ); + }else if(3==args.length){ + return "参数个数不合格!"; + } + else{ + FArray