summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--comment.go26
-rw-r--r--date.go24
-rw-r--r--date_test.go42
-rw-r--r--excelize_test.go1
-rw-r--r--lib.go12
-rw-r--r--sheet.go16
6 files changed, 91 insertions, 30 deletions
diff --git a/comment.go b/comment.go
index b597da1..9548d78 100644
--- a/comment.go
+++ b/comment.go
@@ -3,6 +3,7 @@ package excelize
import (
"encoding/json"
"encoding/xml"
+ "fmt"
"strconv"
"strings"
)
@@ -49,14 +50,23 @@ func (f *File) AddComment(sheet, cell, format string) error {
}
commentsXML := "xl/comments" + strconv.Itoa(commentID) + ".xml"
f.addComment(commentsXML, cell, formatSet)
- f.addDrawingVML(commentID, drawingVML, cell)
+ var colCount int
+ for i, l := range strings.Split(formatSet.Text, "\n") {
+ if ll := len(l); ll > colCount {
+ if i == 0 {
+ ll += len(formatSet.Author)
+ }
+ colCount = ll
+ }
+ }
+ f.addDrawingVML(commentID, drawingVML, cell, strings.Count(formatSet.Text, "\n")+1, colCount)
f.addContentTypePart(commentID, "comments")
return err
}
// addDrawingVML provides function to create comment as
// xl/drawings/vmlDrawing%d.vml by given commit ID and cell.
-func (f *File) addDrawingVML(commentID int, drawingVML, cell string) {
+func (f *File) addDrawingVML(commentID int, drawingVML, cell string, lineCount, colCount int) {
col := string(strings.Map(letterOnlyMapF, cell))
row, _ := strconv.Atoi(strings.Map(intOnlyMapF, cell))
xAxis := row - 1
@@ -83,7 +93,7 @@ func (f *File) addDrawingVML(commentID int, drawingVML, cell string) {
},
VPath: &vPath{
Gradientshapeok: "t",
- Connecttype: "rect",
+ Connecttype: "miter",
},
},
}
@@ -113,10 +123,12 @@ func (f *File) addDrawingVML(commentID int, drawingVML, cell string) {
},
ClientData: &xClientData{
ObjectType: "Note",
- Anchor: "3, 15, 8, 6, 4, 54, 13, 2",
- AutoFill: "False",
- Row: xAxis,
- Column: yAxis,
+ Anchor: fmt.Sprintf(
+ "%d, 23, %d, 0, %d, %d, %d, 5",
+ 1+yAxis, 1+xAxis, 2+yAxis+lineCount, colCount+yAxis, 2+xAxis+lineCount),
+ AutoFill: "True",
+ Row: xAxis,
+ Column: yAxis,
},
}
s, _ := xml.Marshal(sp)
diff --git a/date.go b/date.go
index a493866..f3db0ee 100644
--- a/date.go
+++ b/date.go
@@ -15,7 +15,21 @@ func timeToUTCTime(t time.Time) time.Time {
// timeToExcelTime provides function to convert time to Excel time.
func timeToExcelTime(t time.Time) float64 {
- return float64(t.UnixNano())/8.64e13 + 25569.0
+ // TODO in future this should probably also handle date1904 and like TimeFromExcelTime
+ var excelTime float64
+ var deltaDays int64
+ excelTime = 0
+ deltaDays = 290 * 364
+ // check if UnixNano would be out of int64 range
+ for t.Unix() > deltaDays*24*60*60 {
+ // reduce by aprox. 290 years, which is max for int64 nanoseconds
+ delta := time.Duration(deltaDays) * 24 * time.Hour
+ excelTime = excelTime + float64(deltaDays)
+ t = t.Add(-delta)
+ }
+ // finally add remainder of UnixNano to keep nano precision
+ // and 25569 which is days between 1900 and 1970
+ return excelTime + float64(t.UnixNano())/8.64e13 + 25569.0
}
// shiftJulianToNoon provides function to process julian date to noon.
@@ -90,6 +104,7 @@ func doTheFliegelAndVanFlandernAlgorithm(jd int) (day, month, year int) {
// timeFromExcelTime provides function to convert an excelTime representation
// (stored as a floating point number) to a time.Time.
func timeFromExcelTime(excelTime float64, date1904 bool) time.Time {
+ const MDD int64 = 106750 // Max time.Duration Days, aprox. 290 years
var date time.Time
var intPart = int64(excelTime)
// Excel uses Julian dates prior to March 1st 1900, and Gregorian
@@ -113,6 +128,13 @@ func timeFromExcelTime(excelTime float64, date1904 bool) time.Time {
} else {
date = time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC)
}
+
+ // Duration is limited to aprox. 290 years
+ for intPart > MDD {
+ durationDays := time.Duration(MDD) * time.Hour * 24
+ date = date.Add(durationDays)
+ intPart = intPart - MDD
+ }
durationDays := time.Duration(intPart) * time.Hour * 24
durationPart := time.Duration(dayNanoSeconds * floatPart)
return date.Add(durationDays).Add(durationPart)
diff --git a/date_test.go b/date_test.go
new file mode 100644
index 0000000..bf071e0
--- /dev/null
+++ b/date_test.go
@@ -0,0 +1,42 @@
+package excelize
+
+import (
+ "testing"
+ "time"
+)
+
+type dateTest struct {
+ ExcelValue float64
+ GoValue time.Time
+}
+
+func TestTimeToExcelTime(t *testing.T) {
+ trueExpectedInputList := []dateTest {
+ {0.0, time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC)},
+ {25569.0, time.Unix(0, 0)},
+ {43269.0, time.Date(2018, 6, 18, 0, 0, 0, 0, time.UTC)},
+ {401769.0, time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC)},
+ }
+
+ for _, test := range trueExpectedInputList {
+ if test.ExcelValue != timeToExcelTime(test.GoValue) {
+ t.Fatalf("Expected %v from %v = true, got %v\n", test.ExcelValue, test.GoValue, timeToExcelTime(test.GoValue))
+ }
+ }
+}
+
+func TestTimeFromExcelTime(t *testing.T) {
+ trueExpectedInputList := []dateTest {
+ {0.0, time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC)},
+ {60.0, time.Date(1900, 2, 28, 0, 0, 0, 0, time.UTC)},
+ {61.0, time.Date(1900, 3, 1, 0, 0, 0, 0, time.UTC)},
+ {41275.0, time.Date(2013, 1, 1, 0, 0, 0, 0, time.UTC)},
+ {401769.0, time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC)},
+ }
+
+ for _, test := range trueExpectedInputList {
+ if test.GoValue != timeFromExcelTime(test.ExcelValue, false) {
+ t.Fatalf("Expected %v from %v = true, got %v\n", test.GoValue, test.ExcelValue, timeFromExcelTime(test.ExcelValue, false))
+ }
+ }
+}
diff --git a/excelize_test.go b/excelize_test.go
index 4dbc709..aca33b4 100644
--- a/excelize_test.go
+++ b/excelize_test.go
@@ -88,7 +88,6 @@ func TestOpenFile(t *testing.T) {
xlsx.SetCellValue("Sheet2", "F16", true)
xlsx.SetCellValue("Sheet2", "F17", complex64(5+10i))
t.Log(letterOnlyMapF('x'))
- t.Log(deepCopy(nil, nil))
shiftJulianToNoon(1, -0.6)
timeFromExcelTime(61, true)
timeFromExcelTime(62, true)
diff --git a/lib.go b/lib.go
index fc95b23..4379be4 100644
--- a/lib.go
+++ b/lib.go
@@ -3,7 +3,6 @@ package excelize
import (
"archive/zip"
"bytes"
- "encoding/gob"
"io"
"log"
"math"
@@ -115,17 +114,6 @@ func intOnlyMapF(rune rune) rune {
return -1
}
-// 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)
-}
-
// boolPtr returns a pointer to a bool with the given value.
func boolPtr(b bool) *bool { return &b }
diff --git a/sheet.go b/sheet.go
index 9e8f4c9..5350235 100644
--- a/sheet.go
+++ b/sheet.go
@@ -10,6 +10,8 @@ import (
"strconv"
"strings"
"unicode/utf8"
+
+ "github.com/mohae/deepcopy"
)
// NewSheet provides function to create a new sheet by given worksheet name,
@@ -433,18 +435,15 @@ func (f *File) CopySheet(from, to int) error {
if from < 1 || to < 1 || from == to || f.GetSheetName(from) == "" || f.GetSheetName(to) == "" {
return errors.New("Invalid worksheet index")
}
- return f.copySheet(from, to)
+ f.copySheet(from, to)
+ return nil
}
// copySheet provides function to duplicate a worksheet by gave source and
// target worksheet name.
-func (f *File) copySheet(from, to int) error {
+func (f *File) copySheet(from, to int) {
sheet := f.workSheetReader("sheet" + strconv.Itoa(from))
- worksheet := xlsxWorksheet{}
- err := deepCopy(&worksheet, &sheet)
- if err != nil {
- return err
- }
+ worksheet := deepcopy.Copy(sheet).(*xlsxWorksheet)
path := "xl/worksheets/sheet" + strconv.Itoa(to) + ".xml"
if len(worksheet.SheetViews.SheetView) > 0 {
worksheet.SheetViews.SheetView[0].TabSelected = false
@@ -452,14 +451,13 @@ func (f *File) copySheet(from, to int) error {
worksheet.Drawing = nil
worksheet.TableParts = nil
worksheet.PageSetUp = nil
- f.Sheet[path] = &worksheet
+ f.Sheet[path] = worksheet
toRels := "xl/worksheets/_rels/sheet" + strconv.Itoa(to) + ".xml.rels"
fromRels := "xl/worksheets/_rels/sheet" + strconv.Itoa(from) + ".xml.rels"
_, ok := f.XLSX[fromRels]
if ok {
f.XLSX[toRels] = f.XLSX[fromRels]
}
- return err
}
// SetSheetVisible provides function to set worksheet visible by given worksheet