@ -155,14 +155,15 @@ func (f *File) AddPictureFromBytes(sheet, cell, format, name, extension string,
drawingID := f . countDrawings ( ) + 1
drawingID := f . countDrawings ( ) + 1
drawingXML := "xl/drawings/drawing" + strconv . Itoa ( drawingID ) + ".xml"
drawingXML := "xl/drawings/drawing" + strconv . Itoa ( drawingID ) + ".xml"
drawingID , drawingXML = f . prepareDrawing ( xlsx , drawingID , sheet , drawingXML )
drawingID , drawingXML = f . prepareDrawing ( xlsx , drawingID , sheet , drawingXML )
drawingRels := "xl/drawings/_rels/drawing" + strconv . Itoa ( drawingID ) + ".xml.rels"
mediaStr := ".." + strings . TrimPrefix ( f . addMedia ( file , ext ) , "xl" )
mediaStr := ".." + strings . TrimPrefix ( f . addMedia ( file , ext ) , "xl" )
drawingRID := f . add DrawingRelationships( drawingID , SourceRelationshipImage , mediaStr , hyperlinkType )
drawingRID := f . add Rels( drawingRels , SourceRelationshipImage , mediaStr , hyperlinkType )
// Add picture with hyperlink.
// Add picture with hyperlink.
if formatSet . Hyperlink != "" && formatSet . HyperlinkType != "" {
if formatSet . Hyperlink != "" && formatSet . HyperlinkType != "" {
if formatSet . HyperlinkType == "External" {
if formatSet . HyperlinkType == "External" {
hyperlinkType = formatSet . HyperlinkType
hyperlinkType = formatSet . HyperlinkType
}
}
drawingHyperlinkRID = f . add DrawingRelationships( drawingID , SourceRelationshipHyperLink , formatSet . Hyperlink , hyperlinkType )
drawingHyperlinkRID = f . add Rels( drawingRels , SourceRelationshipHyperLink , formatSet . Hyperlink , hyperlinkType )
}
}
err = f . addDrawingPicture ( sheet , drawingXML , cell , name , img . Width , img . Height , drawingRID , drawingHyperlinkRID , formatSet )
err = f . addDrawingPicture ( sheet , drawingXML , cell , name , img . Width , img . Height , drawingRID , drawingHyperlinkRID , formatSet )
if err != nil {
if err != nil {
@ -172,37 +173,6 @@ func (f *File) AddPictureFromBytes(sheet, cell, format, name, extension string,
return err
return err
}
}
// addSheetRelationships provides a function to add
// xl/worksheets/_rels/sheet%d.xml.rels by given worksheet name, relationship
// type and target.
func ( f * File ) addSheetRelationships ( sheet , relType , target , targetMode string ) int {
name , ok := f . sheetMap [ trimSheetName ( sheet ) ]
if ! ok {
name = strings . ToLower ( sheet ) + ".xml"
}
var rels = "xl/worksheets/_rels/" + strings . TrimPrefix ( name , "xl/worksheets/" ) + ".rels"
sheetRels := f . workSheetRelsReader ( rels )
if sheetRels == nil {
sheetRels = & xlsxWorkbookRels { }
}
var rID = 1
var ID bytes . Buffer
ID . WriteString ( "rId" )
ID . WriteString ( strconv . Itoa ( rID ) )
ID . Reset ( )
rID = len ( sheetRels . Relationships ) + 1
ID . WriteString ( "rId" )
ID . WriteString ( strconv . Itoa ( rID ) )
sheetRels . Relationships = append ( sheetRels . Relationships , xlsxWorkbookRelation {
ID : ID . String ( ) ,
Type : relType ,
Target : target ,
TargetMode : targetMode ,
} )
f . WorkSheetRels [ rels ] = sheetRels
return rID
}
// deleteSheetRelationships provides a function to delete relationships in
// deleteSheetRelationships provides a function to delete relationships in
// xl/worksheets/_rels/sheet%d.xml.rels by given worksheet name and
// xl/worksheets/_rels/sheet%d.xml.rels by given worksheet name and
// relationship index.
// relationship index.
@ -212,16 +182,16 @@ func (f *File) deleteSheetRelationships(sheet, rID string) {
name = strings . ToLower ( sheet ) + ".xml"
name = strings . ToLower ( sheet ) + ".xml"
}
}
var rels = "xl/worksheets/_rels/" + strings . TrimPrefix ( name , "xl/worksheets/" ) + ".rels"
var rels = "xl/worksheets/_rels/" + strings . TrimPrefix ( name , "xl/worksheets/" ) + ".rels"
sheetRels := f . wo rkSheetR elsReader( rels )
sheetRels := f . relsReader( rels )
if sheetRels == nil {
if sheetRels == nil {
sheetRels = & xlsx Workbook Rels{ }
sheetRels = & xlsx Relationship s{ }
}
}
for k , v := range sheetRels . Relationships {
for k , v := range sheetRels . Relationships {
if v . ID == rID {
if v . ID == rID {
sheetRels . Relationships = append ( sheetRels . Relationships [ : k ] , sheetRels . Relationships [ k + 1 : ] ... )
sheetRels . Relationships = append ( sheetRels . Relationships [ : k ] , sheetRels . Relationships [ k + 1 : ] ... )
}
}
}
}
f . WorkSheet Rels[ rels ] = sheetRels
f . Relationship s[ rels ] = sheetRels
}
}
// addSheetLegacyDrawing provides a function to add legacy drawing element to
// addSheetLegacyDrawing provides a function to add legacy drawing element to
@ -325,33 +295,6 @@ func (f *File) addDrawingPicture(sheet, drawingXML, cell, file string, width, he
return err
return err
}
}
// addDrawingRelationships provides a function to add image part relationships
// in the file xl/drawings/_rels/drawing%d.xml.rels by given drawing index,
// relationship type and target.
func ( f * File ) addDrawingRelationships ( index int , relType , target , targetMode string ) int {
var rels = "xl/drawings/_rels/drawing" + strconv . Itoa ( index ) + ".xml.rels"
var rID = 1
var ID bytes . Buffer
ID . WriteString ( "rId" )
ID . WriteString ( strconv . Itoa ( rID ) )
drawingRels := f . drawingRelsReader ( rels )
if drawingRels == nil {
drawingRels = & xlsxWorkbookRels { }
}
ID . Reset ( )
rID = len ( drawingRels . Relationships ) + 1
ID . WriteString ( "rId" )
ID . WriteString ( strconv . Itoa ( rID ) )
drawingRels . Relationships = append ( drawingRels . Relationships , xlsxWorkbookRelation {
ID : ID . String ( ) ,
Type : relType ,
Target : target ,
TargetMode : targetMode ,
} )
f . DrawingRels [ rels ] = drawingRels
return rID
}
// countMedia provides a function to get media files count storage in the
// countMedia provides a function to get media files count storage in the
// folder xl/media/image.
// folder xl/media/image.
func ( f * File ) countMedia ( ) int {
func ( f * File ) countMedia ( ) int {
@ -429,16 +372,20 @@ func (f *File) addContentTypePart(index int, contentType string) {
"drawings" : f . setContentTypePartImageExtensions ,
"drawings" : f . setContentTypePartImageExtensions ,
}
}
partNames := map [ string ] string {
partNames := map [ string ] string {
"chart" : "/xl/charts/chart" + strconv . Itoa ( index ) + ".xml" ,
"chart" : "/xl/charts/chart" + strconv . Itoa ( index ) + ".xml" ,
"comments" : "/xl/comments" + strconv . Itoa ( index ) + ".xml" ,
"comments" : "/xl/comments" + strconv . Itoa ( index ) + ".xml" ,
"drawings" : "/xl/drawings/drawing" + strconv . Itoa ( index ) + ".xml" ,
"drawings" : "/xl/drawings/drawing" + strconv . Itoa ( index ) + ".xml" ,
"table" : "/xl/tables/table" + strconv . Itoa ( index ) + ".xml" ,
"table" : "/xl/tables/table" + strconv . Itoa ( index ) + ".xml" ,
"pivotTable" : "/xl/pivotTables/pivotTable" + strconv . Itoa ( index ) + ".xml" ,
"pivotCache" : "/xl/pivotCache/pivotCacheDefinition" + strconv . Itoa ( index ) + ".xml" ,
}
}
contentTypes := map [ string ] string {
contentTypes := map [ string ] string {
"chart" : "application/vnd.openxmlformats-officedocument.drawingml.chart+xml" ,
"chart" : "application/vnd.openxmlformats-officedocument.drawingml.chart+xml" ,
"comments" : "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml" ,
"comments" : "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml" ,
"drawings" : "application/vnd.openxmlformats-officedocument.drawing+xml" ,
"drawings" : "application/vnd.openxmlformats-officedocument.drawing+xml" ,
"table" : "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml" ,
"table" : "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml" ,
"pivotTable" : "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml" ,
"pivotCache" : "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml" ,
}
}
s , ok := setContentType [ contentType ]
s , ok := setContentType [ contentType ]
if ok {
if ok {
@ -465,9 +412,9 @@ func (f *File) getSheetRelationshipsTargetByID(sheet, rID string) string {
name = strings . ToLower ( sheet ) + ".xml"
name = strings . ToLower ( sheet ) + ".xml"
}
}
var rels = "xl/worksheets/_rels/" + strings . TrimPrefix ( name , "xl/worksheets/" ) + ".rels"
var rels = "xl/worksheets/_rels/" + strings . TrimPrefix ( name , "xl/worksheets/" ) + ".rels"
sheetRels := f . wo rkSheetR elsReader( rels )
sheetRels := f . relsReader( rels )
if sheetRels == nil {
if sheetRels == nil {
sheetRels = & xlsx Workbook Rels{ }
sheetRels = & xlsx Relationship s{ }
}
}
for _ , v := range sheetRels . Relationships {
for _ , v := range sheetRels . Relationships {
if v . ID == rID {
if v . ID == rID {
@ -529,12 +476,12 @@ func (f *File) getPicture(row, col int, drawingXML, drawingRelationships string)
for _ , anchor := range wsDr . TwoCellAnchor {
for _ , anchor := range wsDr . TwoCellAnchor {
if anchor . From != nil && anchor . Pic != nil {
if anchor . From != nil && anchor . Pic != nil {
if anchor . From . Col == col && anchor . From . Row == row {
if anchor . From . Col == col && anchor . From . Row == row {
xlsx Workbook Relation := f . getDrawingRelationships ( drawingRelationships ,
xlsx Relationship := f . getDrawingRelationships ( drawingRelationships ,
anchor . Pic . BlipFill . Blip . Embed )
anchor . Pic . BlipFill . Blip . Embed )
_ , ok := supportImageTypes [ filepath . Ext ( xlsx Workbook Relation. Target ) ]
_ , ok := supportImageTypes [ filepath . Ext ( xlsx Relationship . Target ) ]
if ok {
if ok {
return filepath . Base ( xlsx Workbook Relation. Target ) ,
return filepath . Base ( xlsx Relationship . Target ) ,
[ ] byte ( f . XLSX [ strings . Replace ( xlsx Workbook Relation. Target ,
[ ] byte ( f . XLSX [ strings . Replace ( xlsx Relationship . Target ,
".." , "xl" , - 1 ) ] ) , nil
".." , "xl" , - 1 ) ] ) , nil
}
}
}
}
@ -548,10 +495,10 @@ func (f *File) getPicture(row, col int, drawingXML, drawingRelationships string)
_ = xml . Unmarshal ( [ ] byte ( "<decodeTwoCellAnchor>" + anchor . Content + "</decodeTwoCellAnchor>" ) , & decodeTwoCellAnchor )
_ = xml . Unmarshal ( [ ] byte ( "<decodeTwoCellAnchor>" + anchor . Content + "</decodeTwoCellAnchor>" ) , & decodeTwoCellAnchor )
if decodeTwoCellAnchor . From != nil && decodeTwoCellAnchor . Pic != nil {
if decodeTwoCellAnchor . From != nil && decodeTwoCellAnchor . Pic != nil {
if decodeTwoCellAnchor . From . Col == col && decodeTwoCellAnchor . From . Row == row {
if decodeTwoCellAnchor . From . Col == col && decodeTwoCellAnchor . From . Row == row {
xlsx Workbook Relation := f . getDrawingRelationships ( drawingRelationships , decodeTwoCellAnchor . Pic . BlipFill . Blip . Embed )
xlsx Relationship := f . getDrawingRelationships ( drawingRelationships , decodeTwoCellAnchor . Pic . BlipFill . Blip . Embed )
_ , ok := supportImageTypes [ filepath . Ext ( xlsx Workbook Relation. Target ) ]
_ , ok := supportImageTypes [ filepath . Ext ( xlsx Relationship . Target ) ]
if ok {
if ok {
return filepath . Base ( xlsx Workbook Relation. Target ) , [ ] byte ( f . XLSX [ strings . Replace ( xlsx Workbook Relation. Target , ".." , "xl" , - 1 ) ] ) , nil
return filepath . Base ( xlsx Relationship . Target ) , [ ] byte ( f . XLSX [ strings . Replace ( xlsx Relationship . Target , ".." , "xl" , - 1 ) ] ) , nil
}
}
}
}
}
}
@ -562,8 +509,8 @@ func (f *File) getPicture(row, col int, drawingXML, drawingRelationships string)
// getDrawingRelationships provides a function to get drawing relationships
// getDrawingRelationships provides a function to get drawing relationships
// from xl/drawings/_rels/drawing%s.xml.rels by given file name and
// from xl/drawings/_rels/drawing%s.xml.rels by given file name and
// relationship ID.
// relationship ID.
func ( f * File ) getDrawingRelationships ( rels , rID string ) * xlsx Workbook Relation {
func ( f * File ) getDrawingRelationships ( rels , rID string ) * xlsx Relationship {
if drawingRels := f . d rawingR elsReader( rels ) ; drawingRels != nil {
if drawingRels := f . relsReader( rels ) ; drawingRels != nil {
for _ , v := range drawingRels . Relationships {
for _ , v := range drawingRels . Relationships {
if v . ID == rID {
if v . ID == rID {
return & v
return & v
@ -573,31 +520,6 @@ func (f *File) getDrawingRelationships(rels, rID string) *xlsxWorkbookRelation {
return nil
return nil
}
}
// drawingRelsReader provides a function to get the pointer to the structure
// after deserialization of xl/drawings/_rels/drawing%d.xml.rels.
func ( f * File ) drawingRelsReader ( rel string ) * xlsxWorkbookRels {
if f . DrawingRels [ rel ] == nil {
_ , ok := f . XLSX [ rel ]
if ok {
d := xlsxWorkbookRels { }
_ = xml . Unmarshal ( namespaceStrictToTransitional ( f . readXML ( rel ) ) , & d )
f . DrawingRels [ rel ] = & d
}
}
return f . DrawingRels [ rel ]
}
// drawingRelsWriter provides a function to save
// xl/drawings/_rels/drawing%d.xml.rels after serialize structure.
func ( f * File ) drawingRelsWriter ( ) {
for path , d := range f . DrawingRels {
if d != nil {
v , _ := xml . Marshal ( d )
f . saveFileList ( path , v )
}
}
}
// drawingsWriter provides a function to save xl/drawings/drawing%d.xml after
// drawingsWriter provides a function to save xl/drawings/drawing%d.xml after
// serialize structure.
// serialize structure.
func ( f * File ) drawingsWriter ( ) {
func ( f * File ) drawingsWriter ( ) {