excelize/lib.go

124 lines
2.8 KiB
Go
Raw Normal View History

2016-08-30 11:51:31 +08:00
package excelize
import (
"archive/zip"
"bytes"
"encoding/gob"
2016-08-30 11:51:31 +08:00
"io"
"log"
"math"
)
// ReadZipReader can be used to read an XLSX in memory without touching the
// filesystem.
func ReadZipReader(r *zip.Reader) (map[string]string, int, error) {
fileList := make(map[string]string)
worksheets := 0
2016-08-30 11:51:31 +08:00
for _, v := range r.File {
fileList[v.Name] = readFile(v)
if len(v.Name) > 18 {
if v.Name[0:19] == "xl/worksheets/sheet" {
worksheets++
}
}
2016-08-30 11:51:31 +08:00
}
return fileList, worksheets, nil
2016-08-30 11:51:31 +08:00
}
// readXML provides function to read XML content as string.
func (f *File) readXML(name string) string {
if content, ok := f.XLSX[name]; ok {
return content
2016-08-30 11:51:31 +08:00
}
return ""
2016-08-30 11:51:31 +08:00
}
// saveFileList provides function to update given file content in file list of
// XLSX.
func (f *File) saveFileList(name, content string) {
f.XLSX[name] = XMLHeader + content
2016-08-30 11:51:31 +08:00
}
2016-10-19 20:39:44 +08:00
// Read file content as string in a archive file.
2016-08-30 11:51:31 +08:00
func readFile(file *zip.File) string {
rc, err := file.Open()
if err != nil {
log.Fatal(err)
}
buff := bytes.NewBuffer(nil)
io.Copy(buff, rc)
rc.Close()
return string(buff.Bytes())
}
// ToAlphaString provides function to convert integer to Excel sheet column
// title. For example convert 36 to column title AK:
//
// excelize.ToAlphaString(36)
//
func ToAlphaString(value int) string {
2016-08-30 11:51:31 +08:00
if value < 0 {
return ""
2016-08-30 11:51:31 +08:00
}
var ans string
i := value + 1
2016-08-30 11:51:31 +08:00
for i > 0 {
ans = string((i-1)%26+65) + ans
i = (i - 1) / 26
}
return ans
}
// TitleToNumber provides function to convert Excel sheet column title to int
2017-09-06 12:16:39 +08:00
// (this function doesn't do value check currently). For example convert AK
// and ak to column title 36:
//
// excelize.TitleToNumber("AK")
2017-09-05 18:26:47 +08:00
// excelize.TitleToNumber("ak")
//
func TitleToNumber(s string) int {
2016-08-30 11:51:31 +08:00
weight := 0.0
sum := 0
for i := len(s) - 1; i >= 0; i-- {
2017-09-06 12:16:39 +08:00
ch := int(s[i])
2017-09-05 18:06:38 +08:00
if int(s[i]) >= int('a') && int(s[i]) <= int('z') {
ch = int(s[i]) - 32
}
sum = sum + (ch-int('A')+1)*int(math.Pow(26, weight))
2016-08-30 11:51:31 +08:00
weight++
}
return sum - 1
}
// letterOnlyMapF is used in conjunction with strings.Map to return only the
// characters A-Z and a-z in a string.
func letterOnlyMapF(rune rune) rune {
switch {
case 'A' <= rune && rune <= 'Z':
return rune
case 'a' <= rune && rune <= 'z':
return rune - 32
2016-08-30 11:51:31 +08:00
}
return -1
2016-08-30 11:51:31 +08:00
}
// intOnlyMapF is used in conjunction with strings.Map to return only the
// numeric portions of a string.
func intOnlyMapF(rune rune) rune {
if rune >= 48 && rune < 58 {
return rune
2016-08-30 11:51:31 +08:00
}
return -1
2016-08-30 11:51:31 +08:00
}
// deepCopy provides method to creates a deep copy of whatever is passed to it
// and returns the copy in an interface. The returned value will need to be
// asserted to the correct type.
func deepCopy(dst, src interface{}) error {
var buf bytes.Buffer
if err := gob.NewEncoder(&buf).Encode(src); err != nil {
return err
}
return gob.NewDecoder(bytes.NewBuffer(buf.Bytes())).Decode(dst)
}