forked from p30928647/excelize
ref #65: new formula function PRICE
- fix COUPPCD result accuracy issue - update close spreadsheet example in documentation and README
This commit is contained in:
parent
bda8e7f812
commit
bc3c7d51a2
20
README.md
20
README.md
|
@ -77,6 +77,12 @@ func main() {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer func() {
|
||||||
|
// Close the spreadsheet.
|
||||||
|
if err := f.Close(); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
// Get value from cell by given worksheet name and axis.
|
// Get value from cell by given worksheet name and axis.
|
||||||
cell, err := f.GetCellValue("Sheet1", "B2")
|
cell, err := f.GetCellValue("Sheet1", "B2")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -96,10 +102,6 @@ func main() {
|
||||||
}
|
}
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
}
|
}
|
||||||
// Close the spreadsheet.
|
|
||||||
if err = f.Close(); err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -184,6 +186,12 @@ func main() {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer func() {
|
||||||
|
// Close the spreadsheet.
|
||||||
|
if err := f.Close(); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
// Insert a picture.
|
// Insert a picture.
|
||||||
if err := f.AddPicture("Sheet1", "A2", "image.png", ""); err != nil {
|
if err := f.AddPicture("Sheet1", "A2", "image.png", ""); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
|
@ -207,10 +215,6 @@ func main() {
|
||||||
if err = f.Save(); err != nil {
|
if err = f.Save(); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
// Close the spreadsheet.
|
|
||||||
if err = f.Close(); err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
20
README_zh.md
20
README_zh.md
|
@ -77,6 +77,12 @@ func main() {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer func() {
|
||||||
|
// 关闭工作簿
|
||||||
|
if err := f.Close(); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
// 获取工作表中指定单元格的值
|
// 获取工作表中指定单元格的值
|
||||||
cell, err := f.GetCellValue("Sheet1", "B2")
|
cell, err := f.GetCellValue("Sheet1", "B2")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -96,10 +102,6 @@ func main() {
|
||||||
}
|
}
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
}
|
}
|
||||||
// 关闭工作簿
|
|
||||||
if err = f.Close(); err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -184,6 +186,12 @@ func main() {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer func() {
|
||||||
|
// 关闭工作簿
|
||||||
|
if err := f.Close(); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
// 插入图片
|
// 插入图片
|
||||||
if err := f.AddPicture("Sheet1", "A2", "image.png", ""); err != nil {
|
if err := f.AddPicture("Sheet1", "A2", "image.png", ""); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
|
@ -207,10 +215,6 @@ func main() {
|
||||||
if err = f.Save(); err != nil {
|
if err = f.Save(); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
// 关闭工作簿
|
|
||||||
if err = f.Close(); err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
134
calc.go
134
calc.go
|
@ -516,6 +516,7 @@ type formulaFuncs struct {
|
||||||
// POISSON
|
// POISSON
|
||||||
// POWER
|
// POWER
|
||||||
// PPMT
|
// PPMT
|
||||||
|
// PRICE
|
||||||
// PRICEDISC
|
// PRICEDISC
|
||||||
// PRICEMAT
|
// PRICEMAT
|
||||||
// PRODUCT
|
// PRODUCT
|
||||||
|
@ -9723,6 +9724,40 @@ func (fn *formulaFuncs) COUPDAYSNC(argsList *list.List) formulaArg {
|
||||||
return newNumberFormulaArg(coupdays(settlement, ncd, basis))
|
return newNumberFormulaArg(coupdays(settlement, ncd, basis))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// coupons is an implementation of the formula function COUPNCD and COUPPCD.
|
||||||
|
func (fn *formulaFuncs) coupons(name string, arg formulaArg) formulaArg {
|
||||||
|
settlement := timeFromExcelTime(arg.List[0].Number, false)
|
||||||
|
maturity := timeFromExcelTime(arg.List[1].Number, false)
|
||||||
|
maturityDays := (maturity.Year()-settlement.Year())*12 + (int(maturity.Month()) - int(settlement.Month()))
|
||||||
|
coupon := 12 / int(arg.List[2].Number)
|
||||||
|
mod := maturityDays % coupon
|
||||||
|
year := settlement.Year()
|
||||||
|
month := int(settlement.Month())
|
||||||
|
if mod == 0 && settlement.Day() >= maturity.Day() {
|
||||||
|
month += coupon
|
||||||
|
} else {
|
||||||
|
month += mod
|
||||||
|
}
|
||||||
|
if name != "COUPNCD" {
|
||||||
|
month -= coupon
|
||||||
|
}
|
||||||
|
if month > 11 {
|
||||||
|
year += 1
|
||||||
|
month -= 12
|
||||||
|
} else if month < 0 {
|
||||||
|
year -= 1
|
||||||
|
month += 12
|
||||||
|
}
|
||||||
|
day, lastDay := maturity.Day(), time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
days := getDaysInMonth(lastDay.Year(), int(lastDay.Month()))
|
||||||
|
if getDaysInMonth(maturity.Year(), int(maturity.Month())) == maturity.Day() {
|
||||||
|
day = days
|
||||||
|
} else if day > 27 && day > days {
|
||||||
|
day = days
|
||||||
|
}
|
||||||
|
return newNumberFormulaArg(daysBetween(excelMinTime1900.Unix(), makeDate(year, time.Month(month), day)) + 1)
|
||||||
|
}
|
||||||
|
|
||||||
// COUPNCD function calculates the number of coupons payable, between a
|
// COUPNCD function calculates the number of coupons payable, between a
|
||||||
// security's settlement date and maturity date, rounded up to the nearest
|
// security's settlement date and maturity date, rounded up to the nearest
|
||||||
// whole coupon. The syntax of the function is:
|
// whole coupon. The syntax of the function is:
|
||||||
|
@ -9734,16 +9769,7 @@ func (fn *formulaFuncs) COUPNCD(argsList *list.List) formulaArg {
|
||||||
if args.Type != ArgList {
|
if args.Type != ArgList {
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
settlement := timeFromExcelTime(args.List[0].Number, false)
|
return fn.coupons("COUPNCD", args)
|
||||||
maturity := timeFromExcelTime(args.List[1].Number, false)
|
|
||||||
ncd := time.Date(settlement.Year(), maturity.Month(), maturity.Day(), 0, 0, 0, 0, time.UTC)
|
|
||||||
if ncd.After(settlement) {
|
|
||||||
ncd = ncd.AddDate(-1, 0, 0)
|
|
||||||
}
|
|
||||||
for !ncd.After(settlement) {
|
|
||||||
ncd = ncd.AddDate(0, 12/int(args.List[2].Number), 0)
|
|
||||||
}
|
|
||||||
return newNumberFormulaArg(daysBetween(excelMinTime1900.Unix(), makeDate(ncd.Year(), ncd.Month(), ncd.Day())) + 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// COUPNUM function calculates the number of coupons payable, between a
|
// COUPNUM function calculates the number of coupons payable, between a
|
||||||
|
@ -9773,18 +9799,7 @@ func (fn *formulaFuncs) COUPPCD(argsList *list.List) formulaArg {
|
||||||
if args.Type != ArgList {
|
if args.Type != ArgList {
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
settlement := timeFromExcelTime(args.List[0].Number, false)
|
return fn.coupons("COUPPCD", args)
|
||||||
maturity := timeFromExcelTime(args.List[1].Number, false)
|
|
||||||
date, years := maturity, settlement.Year()-maturity.Year()
|
|
||||||
date = date.AddDate(years, 0, 0)
|
|
||||||
if settlement.After(date) {
|
|
||||||
date = date.AddDate(1, 0, 0)
|
|
||||||
}
|
|
||||||
month := -12 / args.List[2].Number
|
|
||||||
for date.After(settlement) {
|
|
||||||
date = date.AddDate(0, int(month), 0)
|
|
||||||
}
|
|
||||||
return newNumberFormulaArg(daysBetween(excelMinTime1900.Unix(), makeDate(date.Year(), date.Month(), date.Day())) + 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CUMIPMT function calculates the cumulative interest paid on a loan or
|
// CUMIPMT function calculates the cumulative interest paid on a loan or
|
||||||
|
@ -10643,6 +10658,81 @@ func (fn *formulaFuncs) PPMT(argsList *list.List) formulaArg {
|
||||||
return fn.ipmt("PPMT", argsList)
|
return fn.ipmt("PPMT", argsList)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// price is an implementation of the formula function PRICE.
|
||||||
|
func (fn *formulaFuncs) price(settlement, maturity, rate, yld, redemption, frequency, basis formulaArg) formulaArg {
|
||||||
|
if basis.Number < 0 || basis.Number > 4 {
|
||||||
|
return newErrorFormulaArg(formulaErrorNUM, "invalid basis")
|
||||||
|
}
|
||||||
|
argsList := list.New().Init()
|
||||||
|
argsList.PushBack(settlement)
|
||||||
|
argsList.PushBack(maturity)
|
||||||
|
argsList.PushBack(frequency)
|
||||||
|
argsList.PushBack(basis)
|
||||||
|
e := fn.COUPDAYS(argsList)
|
||||||
|
dsc := fn.COUPDAYSNC(argsList).Number / e.Number
|
||||||
|
n := fn.COUPNUM(argsList)
|
||||||
|
a := fn.COUPDAYBS(argsList)
|
||||||
|
ret := redemption.Number / math.Pow(1+yld.Number/frequency.Number, n.Number-1+dsc)
|
||||||
|
ret -= 100 * rate.Number / frequency.Number * a.Number / e.Number
|
||||||
|
t1 := 100 * rate.Number / frequency.Number
|
||||||
|
t2 := 1 + yld.Number/frequency.Number
|
||||||
|
for k := 0.0; k < n.Number; k++ {
|
||||||
|
ret += t1 / math.Pow(t2, k+dsc)
|
||||||
|
}
|
||||||
|
return newNumberFormulaArg(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PRICE function calculates the price, per $100 face value of a security that
|
||||||
|
// pays periodic interest. The syntax of the function is:
|
||||||
|
//
|
||||||
|
// PRICE(settlement,maturity,rate,yld,redemption,frequency,[basis])
|
||||||
|
//
|
||||||
|
func (fn *formulaFuncs) PRICE(argsList *list.List) formulaArg {
|
||||||
|
if argsList.Len() != 6 && argsList.Len() != 7 {
|
||||||
|
return newErrorFormulaArg(formulaErrorVALUE, "PRICE requires 6 or 7 arguments")
|
||||||
|
}
|
||||||
|
args := fn.prepareDataValueArgs(2, argsList)
|
||||||
|
if args.Type != ArgList {
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
settlement, maturity := args.List[0], args.List[1]
|
||||||
|
rate := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
|
||||||
|
if rate.Type != ArgNumber {
|
||||||
|
return rate
|
||||||
|
}
|
||||||
|
if rate.Number < 0 {
|
||||||
|
return newErrorFormulaArg(formulaErrorNUM, "PRICE requires rate >= 0")
|
||||||
|
}
|
||||||
|
yld := argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber()
|
||||||
|
if yld.Type != ArgNumber {
|
||||||
|
return yld
|
||||||
|
}
|
||||||
|
if yld.Number < 0 {
|
||||||
|
return newErrorFormulaArg(formulaErrorNUM, "PRICE requires yld >= 0")
|
||||||
|
}
|
||||||
|
redemption := argsList.Front().Next().Next().Next().Next().Value.(formulaArg).ToNumber()
|
||||||
|
if redemption.Type != ArgNumber {
|
||||||
|
return redemption
|
||||||
|
}
|
||||||
|
if redemption.Number <= 0 {
|
||||||
|
return newErrorFormulaArg(formulaErrorNUM, "PRICE requires redemption > 0")
|
||||||
|
}
|
||||||
|
frequency := argsList.Front().Next().Next().Next().Next().Next().Value.(formulaArg).ToNumber()
|
||||||
|
if frequency.Type != ArgNumber {
|
||||||
|
return frequency
|
||||||
|
}
|
||||||
|
if !validateFrequency(frequency.Number) {
|
||||||
|
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
|
||||||
|
}
|
||||||
|
basis := newNumberFormulaArg(0)
|
||||||
|
if argsList.Len() == 7 {
|
||||||
|
if basis = argsList.Back().Value.(formulaArg).ToNumber(); basis.Type != ArgNumber {
|
||||||
|
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fn.price(settlement, maturity, rate, yld, redemption, frequency, basis)
|
||||||
|
}
|
||||||
|
|
||||||
// PRICEDISC function calculates the price, per $100 face value of a
|
// PRICEDISC function calculates the price, per $100 face value of a
|
||||||
// discounted security. The syntax of the function is:
|
// discounted security. The syntax of the function is:
|
||||||
//
|
//
|
||||||
|
|
21
calc_test.go
21
calc_test.go
|
@ -1429,10 +1429,13 @@ func TestCalcCellValue(t *testing.T) {
|
||||||
"=COUPDAYS(\"01/01/2011\",\"10/25/2012\",4,1)": "92",
|
"=COUPDAYS(\"01/01/2011\",\"10/25/2012\",4,1)": "92",
|
||||||
// COUPDAYSNC
|
// COUPDAYSNC
|
||||||
"=COUPDAYSNC(\"01/01/2011\",\"10/25/2012\",4)": "24",
|
"=COUPDAYSNC(\"01/01/2011\",\"10/25/2012\",4)": "24",
|
||||||
|
"=COUPDAYSNC(\"04/01/2012\",\"03/31/2020\",2)": "179",
|
||||||
// COUPNCD
|
// COUPNCD
|
||||||
"=COUPNCD(\"01/01/2011\",\"10/25/2012\",4)": "40568",
|
"=COUPNCD(\"01/01/2011\",\"10/25/2012\",4)": "40568",
|
||||||
"=COUPNCD(\"01/01/2011\",\"10/25/2012\",4,0)": "40568",
|
"=COUPNCD(\"01/01/2011\",\"10/25/2012\",4,0)": "40568",
|
||||||
"=COUPNCD(\"10/25/2011\",\"01/01/2012\",4)": "40909",
|
"=COUPNCD(\"10/25/2011\",\"01/01/2012\",4)": "40909",
|
||||||
|
"=COUPNCD(\"04/01/2012\",\"03/31/2020\",2)": "41182",
|
||||||
|
"=COUPNCD(\"01/01/2000\",\"08/30/2001\",2)": "36585",
|
||||||
// COUPNUM
|
// COUPNUM
|
||||||
"=COUPNUM(\"01/01/2011\",\"10/25/2012\",4)": "8",
|
"=COUPNUM(\"01/01/2011\",\"10/25/2012\",4)": "8",
|
||||||
"=COUPNUM(\"01/01/2011\",\"10/25/2012\",4,0)": "8",
|
"=COUPNUM(\"01/01/2011\",\"10/25/2012\",4,0)": "8",
|
||||||
|
@ -1497,6 +1500,10 @@ func TestCalcCellValue(t *testing.T) {
|
||||||
// PMT
|
// PMT
|
||||||
"=PMT(0,8,0,5000,1)": "-625",
|
"=PMT(0,8,0,5000,1)": "-625",
|
||||||
"=PMT(0.035/4,8,0,5000,1)": "-600.8520271804658",
|
"=PMT(0.035/4,8,0,5000,1)": "-600.8520271804658",
|
||||||
|
// PRICE
|
||||||
|
"=PRICE(\"04/01/2012\",\"02/01/2020\",12%,10%,100,2)": "110.65510517844305",
|
||||||
|
"=PRICE(\"04/01/2012\",\"02/01/2020\",12%,10%,100,2,4)": "110.65510517844305",
|
||||||
|
"=PRICE(\"04/01/2012\",\"03/31/2020\",12%,10%,100,2)": "110.83448359321572",
|
||||||
// PPMT
|
// PPMT
|
||||||
"=PPMT(0.05/12,2,60,50000)": "-738.2918003208238",
|
"=PPMT(0.05/12,2,60,50000)": "-738.2918003208238",
|
||||||
"=PPMT(0.035/4,2,8,0,5000,1)": "-606.1094824182949",
|
"=PPMT(0.035/4,2,8,0,5000,1)": "-606.1094824182949",
|
||||||
|
@ -2951,6 +2958,20 @@ func TestCalcCellValue(t *testing.T) {
|
||||||
"=PMT(0,0,\"\",0,0)": "strconv.ParseFloat: parsing \"\": invalid syntax",
|
"=PMT(0,0,\"\",0,0)": "strconv.ParseFloat: parsing \"\": invalid syntax",
|
||||||
"=PMT(0,0,0,\"\",0)": "strconv.ParseFloat: parsing \"\": invalid syntax",
|
"=PMT(0,0,0,\"\",0)": "strconv.ParseFloat: parsing \"\": invalid syntax",
|
||||||
"=PMT(0,0,0,0,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
|
"=PMT(0,0,0,0,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
|
||||||
|
// PRICE
|
||||||
|
"=PRICE()": "PRICE requires 6 or 7 arguments",
|
||||||
|
"=PRICE(\"\",\"02/01/2020\",12%,10%,100,2,4)": "#VALUE!",
|
||||||
|
"=PRICE(\"04/01/2012\",\"\",12%,10%,100,2,4)": "#VALUE!",
|
||||||
|
"=PRICE(\"04/01/2012\",\"02/01/2020\",\"\",10%,100,2,4)": "strconv.ParseFloat: parsing \"\": invalid syntax",
|
||||||
|
"=PRICE(\"04/01/2012\",\"02/01/2020\",12%,\"\",100,2,4)": "strconv.ParseFloat: parsing \"\": invalid syntax",
|
||||||
|
"=PRICE(\"04/01/2012\",\"02/01/2020\",12%,10%,\"\",2,4)": "strconv.ParseFloat: parsing \"\": invalid syntax",
|
||||||
|
"=PRICE(\"04/01/2012\",\"02/01/2020\",12%,10%,100,\"\",4)": "strconv.ParseFloat: parsing \"\": invalid syntax",
|
||||||
|
"=PRICE(\"04/01/2012\",\"02/01/2020\",-1,10%,100,2,4)": "PRICE requires rate >= 0",
|
||||||
|
"=PRICE(\"04/01/2012\",\"02/01/2020\",12%,-1,100,2,4)": "PRICE requires yld >= 0",
|
||||||
|
"=PRICE(\"04/01/2012\",\"02/01/2020\",12%,10%,0,2,4)": "PRICE requires redemption > 0",
|
||||||
|
"=PRICE(\"04/01/2012\",\"02/01/2020\",12%,10%,100,2,\"\")": "#NUM!",
|
||||||
|
"=PRICE(\"04/01/2012\",\"02/01/2020\",12%,10%,100,3,4)": "#NUM!",
|
||||||
|
"=PRICE(\"04/01/2012\",\"02/01/2020\",12%,10%,100,2,5)": "invalid basis",
|
||||||
// PPMT
|
// PPMT
|
||||||
"=PPMT()": "PPMT requires at least 4 arguments",
|
"=PPMT()": "PPMT requires at least 4 arguments",
|
||||||
"=PPMT(0,0,0,0,0,0,0)": "PPMT allows at most 6 arguments",
|
"=PPMT(0,0,0,0,0,0,0)": "PPMT allows at most 6 arguments",
|
||||||
|
|
4
cell.go
4
cell.go
|
@ -354,7 +354,7 @@ func (f *File) SetCellStr(sheet, axis, value string) error {
|
||||||
// table.
|
// table.
|
||||||
func (f *File) setCellString(value string) (t string, v string) {
|
func (f *File) setCellString(value string) (t string, v string) {
|
||||||
if len(value) > TotalCellChars {
|
if len(value) > TotalCellChars {
|
||||||
value = value[0:TotalCellChars]
|
value = value[:TotalCellChars]
|
||||||
}
|
}
|
||||||
t = "s"
|
t = "s"
|
||||||
v = strconv.Itoa(f.setSharedString(value))
|
v = strconv.Itoa(f.setSharedString(value))
|
||||||
|
@ -381,7 +381,7 @@ func (f *File) setSharedString(val string) int {
|
||||||
// setCellStr provides a function to set string type to cell.
|
// setCellStr provides a function to set string type to cell.
|
||||||
func setCellStr(value string) (t string, v string, ns xml.Attr) {
|
func setCellStr(value string) (t string, v string, ns xml.Attr) {
|
||||||
if len(value) > TotalCellChars {
|
if len(value) > TotalCellChars {
|
||||||
value = value[0:TotalCellChars]
|
value = value[:TotalCellChars]
|
||||||
}
|
}
|
||||||
if len(value) > 0 {
|
if len(value) > 0 {
|
||||||
prefix, suffix := value[0], value[len(value)-1]
|
prefix, suffix := value[0], value[len(value)-1]
|
||||||
|
|
4
crypt.go
4
crypt.go
|
@ -297,7 +297,7 @@ func encryptionMechanism(buffer []byte) (mechanism string, err error) {
|
||||||
err = ErrUnknownEncryptMechanism
|
err = ErrUnknownEncryptMechanism
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
versionMajor, versionMinor := binary.LittleEndian.Uint16(buffer[0:2]), binary.LittleEndian.Uint16(buffer[2:4])
|
versionMajor, versionMinor := binary.LittleEndian.Uint16(buffer[:2]), binary.LittleEndian.Uint16(buffer[2:4])
|
||||||
if versionMajor == 4 && versionMinor == 4 {
|
if versionMajor == 4 && versionMinor == 4 {
|
||||||
mechanism = "agile"
|
mechanism = "agile"
|
||||||
return
|
return
|
||||||
|
@ -600,7 +600,7 @@ func createIV(blockKey interface{}, encryption Encryption) ([]byte, error) {
|
||||||
tmp := make([]byte, 0x36)
|
tmp := make([]byte, 0x36)
|
||||||
iv = append(iv, tmp...)
|
iv = append(iv, tmp...)
|
||||||
} else if len(iv) > encryptedKey.BlockSize {
|
} else if len(iv) > encryptedKey.BlockSize {
|
||||||
iv = iv[0:encryptedKey.BlockSize]
|
iv = iv[:encryptedKey.BlockSize]
|
||||||
}
|
}
|
||||||
return iv, nil
|
return iv, nil
|
||||||
}
|
}
|
||||||
|
|
2
lib.go
2
lib.go
|
@ -526,7 +526,7 @@ func bytesReplace(s, old, new []byte, n int) []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
w += copy(s[w:], s[i:])
|
w += copy(s[w:], s[i:])
|
||||||
return s[0:w]
|
return s[:w]
|
||||||
}
|
}
|
||||||
|
|
||||||
// genSheetPasswd provides a method to generate password for worksheet
|
// genSheetPasswd provides a method to generate password for worksheet
|
||||||
|
|
13
picture.go
13
picture.go
|
@ -481,14 +481,20 @@ func (f *File) getSheetRelationshipsTargetByID(sheet, rID string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPicture provides a function to get picture base name and raw content
|
// GetPicture provides a function to get picture base name and raw content
|
||||||
// embed in XLSX by given worksheet and cell name. This function returns the
|
// embed in spreadsheet by given worksheet and cell name. This function
|
||||||
// file name in XLSX and file contents as []byte data types. For example:
|
// returns the file name in spreadsheet and file contents as []byte data
|
||||||
|
// types. For example:
|
||||||
//
|
//
|
||||||
// f, err := excelize.OpenFile("Book1.xlsx")
|
// f, err := excelize.OpenFile("Book1.xlsx")
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// fmt.Println(err)
|
// fmt.Println(err)
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
|
// defer func() {
|
||||||
|
// if err := f.Close(); err != nil {
|
||||||
|
// fmt.Println(err)
|
||||||
|
// }
|
||||||
|
// }()
|
||||||
// file, raw, err := f.GetPicture("Sheet1", "A2")
|
// file, raw, err := f.GetPicture("Sheet1", "A2")
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// fmt.Println(err)
|
// fmt.Println(err)
|
||||||
|
@ -497,9 +503,6 @@ func (f *File) getSheetRelationshipsTargetByID(sheet, rID string) string {
|
||||||
// if err := ioutil.WriteFile(file, raw, 0644); err != nil {
|
// if err := ioutil.WriteFile(file, raw, 0644); err != nil {
|
||||||
// fmt.Println(err)
|
// fmt.Println(err)
|
||||||
// }
|
// }
|
||||||
// if err = f.Close(); err != nil {
|
|
||||||
// fmt.Println(err)
|
|
||||||
// }
|
|
||||||
//
|
//
|
||||||
func (f *File) GetPicture(sheet, cell string) (string, []byte, error) {
|
func (f *File) GetPicture(sheet, cell string) (string, []byte, error) {
|
||||||
col, row, err := CellNameToCoordinates(cell)
|
col, row, err := CellNameToCoordinates(cell)
|
||||||
|
|
10
sheet.go
10
sheet.go
|
@ -234,7 +234,7 @@ func trimCell(column []xlsxC) []xlsxC {
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return col[0:i]
|
return col[:i]
|
||||||
}
|
}
|
||||||
|
|
||||||
// setContentTypes provides a function to read and update property of contents
|
// setContentTypes provides a function to read and update property of contents
|
||||||
|
@ -452,12 +452,14 @@ func (f *File) GetSheetIndex(name string) int {
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
|
// defer func() {
|
||||||
|
// if err := f.Close(); err != nil {
|
||||||
|
// fmt.Println(err)
|
||||||
|
// }
|
||||||
|
// }()
|
||||||
// for index, name := range f.GetSheetMap() {
|
// for index, name := range f.GetSheetMap() {
|
||||||
// fmt.Println(index, name)
|
// fmt.Println(index, name)
|
||||||
// }
|
// }
|
||||||
// if err = f.Close(); err != nil {
|
|
||||||
// fmt.Println(err)
|
|
||||||
// }
|
|
||||||
//
|
//
|
||||||
func (f *File) GetSheetMap() map[int]string {
|
func (f *File) GetSheetMap() map[int]string {
|
||||||
wb := f.workbookReader()
|
wb := f.workbookReader()
|
||||||
|
|
|
@ -3137,7 +3137,7 @@ func ThemeColor(baseColor string, tint float64) string {
|
||||||
if tint == 0 {
|
if tint == 0 {
|
||||||
return "FF" + baseColor
|
return "FF" + baseColor
|
||||||
}
|
}
|
||||||
r, _ := strconv.ParseUint(baseColor[0:2], 16, 64)
|
r, _ := strconv.ParseUint(baseColor[:2], 16, 64)
|
||||||
g, _ := strconv.ParseUint(baseColor[2:4], 16, 64)
|
g, _ := strconv.ParseUint(baseColor[2:4], 16, 64)
|
||||||
b, _ := strconv.ParseUint(baseColor[4:6], 16, 64)
|
b, _ := strconv.ParseUint(baseColor[4:6], 16, 64)
|
||||||
var h, s, l float64
|
var h, s, l float64
|
||||||
|
|
2
table.go
2
table.go
|
@ -446,7 +446,7 @@ func (f *File) parseFilterExpression(expression string, tokens []string) ([]int,
|
||||||
if re {
|
if re {
|
||||||
conditional = 1
|
conditional = 1
|
||||||
}
|
}
|
||||||
expression1, token1, err := f.parseFilterTokens(expression, tokens[0:3])
|
expression1, token1, err := f.parseFilterTokens(expression, tokens[:3])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return expressions, t, err
|
return expressions, t, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue