New function `AddPictureFromBytes()` has been added, this resolve #259 and close #271.

formula
xuri 6 years ago
parent 4f47737d64
commit 6ced438f39
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7

@ -29,8 +29,8 @@ func parseFormatCommentsSet(formatSet string) (*formatComment, error) {
// GetComments retrieves all comments and returns a map of worksheet name to // GetComments retrieves all comments and returns a map of worksheet name to
// the worksheet comments. // the worksheet comments.
func (f *File) GetComments() (comments map[string]*xlsxComments) { func (f *File) GetComments() (comments map[string][]Comment) {
comments = map[string]*xlsxComments{} comments = map[string][]Comment{}
for n := range f.sheetMap { for n := range f.sheetMap {
commentID := f.GetSheetIndex(n) commentID := f.GetSheetIndex(n)
commentsXML := "xl/comments" + strconv.Itoa(commentID) + ".xml" commentsXML := "xl/comments" + strconv.Itoa(commentID) + ".xml"
@ -38,7 +38,20 @@ func (f *File) GetComments() (comments map[string]*xlsxComments) {
if ok { if ok {
d := xlsxComments{} d := xlsxComments{}
xml.Unmarshal([]byte(c), &d) 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 return

@ -8,9 +8,7 @@
// the LICENSE file. // the LICENSE file.
package excelize package excelize
import ( import "testing"
"testing"
)
func TestDataValidation(t *testing.T) { func TestDataValidation(t *testing.T) {
xlsx := NewFile() xlsx := NewFile()

@ -1,42 +1,42 @@
package excelize package excelize
import ( import (
"testing" "testing"
"time" "time"
) )
type dateTest struct { type dateTest struct {
ExcelValue float64 ExcelValue float64
GoValue time.Time GoValue time.Time
} }
func TestTimeToExcelTime(t *testing.T) { func TestTimeToExcelTime(t *testing.T) {
trueExpectedInputList := []dateTest { trueExpectedInputList := []dateTest{
{0.0, time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC)}, {0.0, time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC)},
{25569.0, time.Unix(0, 0)}, {25569.0, time.Unix(0, 0)},
{43269.0, time.Date(2018, 6, 18, 0, 0, 0, 0, time.UTC)}, {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)}, {401769.0, time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC)},
} }
for _, test := range trueExpectedInputList { for _, test := range trueExpectedInputList {
if test.ExcelValue != timeToExcelTime(test.GoValue) { if test.ExcelValue != timeToExcelTime(test.GoValue) {
t.Fatalf("Expected %v from %v = true, got %v\n", test.ExcelValue, test.GoValue, 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) { func TestTimeFromExcelTime(t *testing.T) {
trueExpectedInputList := []dateTest { trueExpectedInputList := []dateTest{
{0.0, time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC)}, {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)}, {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)}, {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)}, {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)}, {401769.0, time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC)},
} }
for _, test := range trueExpectedInputList { for _, test := range trueExpectedInputList {
if test.GoValue != timeFromExcelTime(test.ExcelValue, false) { 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)) t.Fatalf("Expected %v from %v = true, got %v\n", test.GoValue, test.ExcelValue, timeFromExcelTime(test.ExcelValue, false))
} }
} }
} }

@ -162,6 +162,24 @@ func TestAddPicture(t *testing.T) {
if err != nil { if err != nil {
t.Log(err) 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. // Test write file to given path.
err = xlsx.SaveAs("./test/Book2.xlsx") err = xlsx.SaveAs("./test/Book2.xlsx")
if err != nil { if err != nil {
@ -211,8 +229,13 @@ func TestNewFile(t *testing.T) {
if err != nil { if err != nil {
t.Error(err) 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", "") 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 { if err != nil {
t.Log(err) t.Log(err)
} }

@ -86,8 +86,6 @@ func parseFormatPictureSet(formatSet string) (*formatPicture, error) {
// positioning is move and size with cells. // positioning is move and size with cells.
func (f *File) AddPicture(sheet, cell, picture, format string) error { func (f *File) AddPicture(sheet, cell, picture, format string) error {
var err error var err error
var drawingHyperlinkRID int
var hyperlinkType string
// Check picture exists first. // Check picture exists first.
if _, err = os.Stat(picture); os.IsNotExist(err) { if _, err = os.Stat(picture); os.IsNotExist(err) {
return err return err
@ -96,14 +94,55 @@ func (f *File) AddPicture(sheet, cell, picture, format string) error {
if !ok { if !ok {
return errors.New("unsupported image extension") 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 { if err != nil {
return err return err
} }
defer readFile.Close() image, _, err := image.DecodeConfig(bytes.NewReader(file))
image, _, _ := image.DecodeConfig(readFile)
_, file := filepath.Split(picture)
formatSet, err := parseFormatPictureSet(format)
if err != nil { if err != nil {
return err return err
} }
@ -122,8 +161,8 @@ func (f *File) AddPicture(sheet, cell, picture, format string) error {
} }
drawingHyperlinkRID = f.addDrawingRelationships(drawingID, SourceRelationshipHyperLink, formatSet.Hyperlink, hyperlinkType) drawingHyperlinkRID = f.addDrawingRelationships(drawingID, SourceRelationshipHyperLink, formatSet.Hyperlink, hyperlinkType)
} }
f.addDrawingPicture(sheet, drawingXML, cell, file, image.Width, image.Height, drawingRID, drawingHyperlinkRID, formatSet) f.addDrawingPicture(sheet, drawingXML, cell, name, image.Width, image.Height, drawingRID, drawingHyperlinkRID, formatSet)
f.addMedia(picture, ext) f.addMedia(file, ext)
f.addContentTypePart(drawingID, "drawings") f.addContentTypePart(drawingID, "drawings")
return err return err
} }
@ -317,12 +356,11 @@ func (f *File) countMedia() int {
} }
// addMedia provides a function to add picture into folder xl/media/image by // addMedia provides a function to add picture into folder xl/media/image by
// given file name and extension name. // given file and extension name.
func (f *File) addMedia(file, ext string) { func (f *File) addMedia(file []byte, ext string) {
count := f.countMedia() count := f.countMedia()
dat, _ := ioutil.ReadFile(file)
media := "xl/media/image" + strconv.Itoa(count+1) + ext 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 // setContentTypePartImageExtensions provides a function to set the content

@ -13,6 +13,7 @@ import (
"encoding/json" "encoding/json"
"encoding/xml" "encoding/xml"
"errors" "errors"
"io/ioutil"
"os" "os"
"path" "path"
"strconv" "strconv"
@ -370,7 +371,7 @@ func (f *File) getSheetMap() map[string]string {
} }
// SetSheetBackground provides a function to set background picture by given // 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 { func (f *File) SetSheetBackground(sheet, picture string) error {
var err error var err error
// Check picture exists first. // Check picture exists first.
@ -384,7 +385,8 @@ func (f *File) SetSheetBackground(sheet, picture string) error {
pictureID := f.countMedia() + 1 pictureID := f.countMedia() + 1
rID := f.addSheetRelationships(sheet, SourceRelationshipImage, "../media/image"+strconv.Itoa(pictureID)+ext, "") rID := f.addSheetRelationships(sheet, SourceRelationshipImage, "../media/image"+strconv.Itoa(pictureID)+ext, "")
f.addSheetPicture(sheet, rID) f.addSheetPicture(sheet, rID)
f.addMedia(picture, ext) file, _ := ioutil.ReadFile(picture)
f.addMedia(file, ext)
f.setContentTypePartImageExtensions() f.setContentTypePartImageExtensions()
return err return err
} }

@ -61,3 +61,11 @@ type formatComment struct {
Author string `json:"author"` Author string `json:"author"`
Text string `json:"text"` 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"`
}

Loading…
Cancel
Save