diff --git a/comment.go b/comment.go index 32ed02f..94aad6c 100644 --- a/comment.go +++ b/comment.go @@ -29,8 +29,8 @@ func parseFormatCommentsSet(formatSet string) (*formatComment, error) { // GetComments retrieves all comments and returns a map of worksheet name to // the worksheet comments. -func (f *File) GetComments() (comments map[string]*xlsxComments) { - comments = map[string]*xlsxComments{} +func (f *File) GetComments() (comments map[string][]Comment) { + comments = map[string][]Comment{} for n := range f.sheetMap { commentID := f.GetSheetIndex(n) commentsXML := "xl/comments" + strconv.Itoa(commentID) + ".xml" @@ -38,7 +38,20 @@ func (f *File) GetComments() (comments map[string]*xlsxComments) { if ok { d := xlsxComments{} xml.Unmarshal([]byte(c), &d) - comments[n] = &d + sheetComments := []Comment{} + for _, comment := range d.CommentList.Comment { + sheetComment := Comment{} + if comment.AuthorID < len(d.Authors) { + sheetComment.Author = d.Authors[comment.AuthorID].Author + } + sheetComment.Ref = comment.Ref + sheetComment.AuthorID = comment.AuthorID + for _, text := range comment.Text.R { + sheetComment.Text += text.T + } + sheetComments = append(sheetComments, sheetComment) + } + comments[n] = sheetComments } } return diff --git a/datavalidation_test.go b/datavalidation_test.go index 9899334..0f50f29 100644 --- a/datavalidation_test.go +++ b/datavalidation_test.go @@ -8,9 +8,7 @@ // the LICENSE file. package excelize -import ( - "testing" -) +import "testing" func TestDataValidation(t *testing.T) { xlsx := NewFile() diff --git a/date_test.go b/date_test.go index bf071e0..06421b8 100644 --- a/date_test.go +++ b/date_test.go @@ -1,42 +1,42 @@ package excelize import ( - "testing" - "time" + "testing" + "time" ) type dateTest struct { - ExcelValue float64 - GoValue time.Time + 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)}, - } + 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)) - } - } + 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)}, - } + 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)) - } - } + 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 c9a87d0..9f738f3 100644 --- a/excelize_test.go +++ b/excelize_test.go @@ -162,6 +162,24 @@ func TestAddPicture(t *testing.T) { if err != nil { t.Log(err) } + err = xlsx.AddPictureFromBytes("Sheet1", "G21", "", "Excel Logo", "jpg", make([]byte, 1)) + if err != nil { + t.Log(err) + } + // Test add picture to worksheet with invalid file data. + err = xlsx.AddPictureFromBytes("Sheet1", "G21", "", "Excel Logo", ".jpg", make([]byte, 1)) + if err != nil { + t.Log(err) + } + file, err := ioutil.ReadFile("./test/images/excel.jpg") + if err != nil { + t.Error(err) + } + // Test add picture to worksheet from bytes. + err = xlsx.AddPictureFromBytes("Sheet1", "Q1", "", "Excel Logo", ".jpg", file) + if err != nil { + t.Log(err) + } // Test write file to given path. err = xlsx.SaveAs("./test/Book2.xlsx") if err != nil { @@ -211,8 +229,13 @@ func TestNewFile(t *testing.T) { if err != nil { t.Error(err) } - // Test add picture to worksheet with invalid formatset + // Test add picture to worksheet without formatset. err = xlsx.AddPicture("Sheet1", "C2", "./test/images/excel.png", "") + if err != nil { + t.Error(err) + } + // Test add picture to worksheet with invalid formatset. + err = xlsx.AddPicture("Sheet1", "C2", "./test/images/excel.png", `{`) if err != nil { t.Log(err) } diff --git a/picture.go b/picture.go index decc37d..e473498 100644 --- a/picture.go +++ b/picture.go @@ -86,8 +86,6 @@ func parseFormatPictureSet(formatSet string) (*formatPicture, error) { // positioning is move and size with cells. func (f *File) AddPicture(sheet, cell, picture, format string) error { var err error - var drawingHyperlinkRID int - var hyperlinkType string // Check picture exists first. if _, err = os.Stat(picture); os.IsNotExist(err) { return err @@ -96,14 +94,55 @@ func (f *File) AddPicture(sheet, cell, picture, format string) error { if !ok { return errors.New("unsupported image extension") } - readFile, err := os.Open(picture) + file, _ := ioutil.ReadFile(picture) + _, name := filepath.Split(picture) + return f.AddPictureFromBytes(sheet, cell, format, name, ext, file) +} + +// AddPictureFromBytes provides the method to add picture in a sheet by given +// picture format set (such as offset, scale, aspect ratio setting and print +// settings), file base name, extension name and file bytes. For example: +// +// package main +// +// import ( +// "fmt" +// _ "image/jpeg" +// "io/ioutil" +// +// "github.com/360EntSecGroup-Skylar/excelize" +// ) +// +// func main() { +// xlsx := excelize.NewFile() +// +// file, err := ioutil.ReadFile("./image1.jpg") +// if err != nil { +// fmt.Println(err) +// } +// err = xlsx.AddPictureFromBytes("Sheet1", "A2", "", "Excel Logo", ".jpg", file) +// if err != nil { +// fmt.Println(err) +// } +// err = xlsx.SaveAs("./Book1.xlsx") +// if err != nil { +// fmt.Println(err) +// } +// } +// +func (f *File) AddPictureFromBytes(sheet, cell, format, name, extension string, file []byte) error { + var err error + var drawingHyperlinkRID int + var hyperlinkType string + ext, ok := supportImageTypes[extension] + if !ok { + return errors.New("unsupported image extension") + } + formatSet, err := parseFormatPictureSet(format) if err != nil { return err } - defer readFile.Close() - image, _, _ := image.DecodeConfig(readFile) - _, file := filepath.Split(picture) - formatSet, err := parseFormatPictureSet(format) + image, _, err := image.DecodeConfig(bytes.NewReader(file)) if err != nil { return err } @@ -122,8 +161,8 @@ func (f *File) AddPicture(sheet, cell, picture, format string) error { } drawingHyperlinkRID = f.addDrawingRelationships(drawingID, SourceRelationshipHyperLink, formatSet.Hyperlink, hyperlinkType) } - f.addDrawingPicture(sheet, drawingXML, cell, file, image.Width, image.Height, drawingRID, drawingHyperlinkRID, formatSet) - f.addMedia(picture, ext) + f.addDrawingPicture(sheet, drawingXML, cell, name, image.Width, image.Height, drawingRID, drawingHyperlinkRID, formatSet) + f.addMedia(file, ext) f.addContentTypePart(drawingID, "drawings") return err } @@ -317,12 +356,11 @@ func (f *File) countMedia() int { } // addMedia provides a function to add picture into folder xl/media/image by -// given file name and extension name. -func (f *File) addMedia(file, ext string) { +// given file and extension name. +func (f *File) addMedia(file []byte, ext string) { count := f.countMedia() - dat, _ := ioutil.ReadFile(file) media := "xl/media/image" + strconv.Itoa(count+1) + ext - f.XLSX[media] = dat + f.XLSX[media] = file } // setContentTypePartImageExtensions provides a function to set the content diff --git a/sheet.go b/sheet.go index b5c3e6c..ef2b6f4 100644 --- a/sheet.go +++ b/sheet.go @@ -13,6 +13,7 @@ import ( "encoding/json" "encoding/xml" "errors" + "io/ioutil" "os" "path" "strconv" @@ -370,7 +371,7 @@ func (f *File) getSheetMap() map[string]string { } // SetSheetBackground provides a function to set background picture by given -// worksheet name. +// worksheet name and file path. func (f *File) SetSheetBackground(sheet, picture string) error { var err error // Check picture exists first. @@ -384,7 +385,8 @@ func (f *File) SetSheetBackground(sheet, picture string) error { pictureID := f.countMedia() + 1 rID := f.addSheetRelationships(sheet, SourceRelationshipImage, "../media/image"+strconv.Itoa(pictureID)+ext, "") f.addSheetPicture(sheet, rID) - f.addMedia(picture, ext) + file, _ := ioutil.ReadFile(picture) + f.addMedia(file, ext) f.setContentTypePartImageExtensions() return err } diff --git a/xmlComments.go b/xmlComments.go index 08d85c1..1607506 100644 --- a/xmlComments.go +++ b/xmlComments.go @@ -61,3 +61,11 @@ type formatComment struct { Author string `json:"author"` Text string `json:"text"` } + +// Comment directly maps the comment information. +type Comment struct { + Author string `json:"author"` + AuthorID int `json:"author_id"` + Ref string `json:"ref"` + Text string `json:"text"` +}