Resolve #217, new function add VBA project supported.

This commit is contained in:
xuri 2019-07-21 12:56:36 +08:00
parent 855c3605f6
commit 35e485756f
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7
4 changed files with 89 additions and 0 deletions

View File

@ -19,7 +19,9 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"path"
"strconv" "strconv"
"strings"
) )
// File define a populated XLSX file struct. // File define a populated XLSX file struct.
@ -226,3 +228,78 @@ func (f *File) UpdateLinkedValue() error {
} }
return nil return nil
} }
// AddVBAProject provides the method to add vbaProject.bin file which contains
// functions and/or macros. The file extension should be .xlsm. For example:
//
// err := f.SetSheetPrOptions("Sheet1", excelize.CodeName("Sheet1"))
// if err != nil {
// fmt.Println(err)
// }
// err = f.AddVBAProject("vbaProject.bin")
// if err != nil {
// fmt.Println(err)
// }
// err = f.SaveAs("macros.xlsm")
// if err != nil {
// fmt.Println(err)
// }
//
func (f *File) AddVBAProject(bin string) error {
var err error
// Check vbaProject.bin exists first.
if _, err = os.Stat(bin); os.IsNotExist(err) {
return err
}
if path.Ext(bin) != ".bin" {
return errors.New("unsupported VBA project extension")
}
f.setContentTypePartVBAProjectExtensions()
wb := f.workbookRelsReader()
var rID int
var ok bool
for _, rel := range wb.Relationships {
if rel.Target == "vbaProject.bin" && rel.Type == SourceRelationshipVBAProject {
ok = true
continue
}
t, _ := strconv.Atoi(strings.TrimPrefix(rel.ID, "rId"))
if t > rID {
rID = t
}
}
rID++
if !ok {
wb.Relationships = append(wb.Relationships, xlsxWorkbookRelation{
ID: "rId" + strconv.Itoa(rID),
Target: "vbaProject.bin",
Type: SourceRelationshipVBAProject,
})
}
file, _ := ioutil.ReadFile(bin)
f.XLSX["xl/vbaProject.bin"] = file
return err
}
// setContentTypePartVBAProjectExtensions provides a function to set the
// content type for relationship parts and the main document part.
func (f *File) setContentTypePartVBAProjectExtensions() {
var ok bool
content := f.contentTypesReader()
for _, v := range content.Defaults {
if v.Extension == "bin" {
ok = true
}
}
for idx, o := range content.Overrides {
if o.PartName == "/xl/workbook.xml" {
content.Overrides[idx].ContentType = "application/vnd.ms-excel.sheet.macroEnabled.main+xml"
}
}
if !ok {
content.Defaults = append(content.Defaults, xlsxDefault{
Extension: "bin",
ContentType: "application/vnd.ms-office.vbaProject",
})
}
}

View File

@ -1078,6 +1078,17 @@ func TestSetDefaultTimeStyle(t *testing.T) {
assert.EqualError(t, f.setDefaultTimeStyle("SheetN", "", 0), "sheet SheetN is not exist") assert.EqualError(t, f.setDefaultTimeStyle("SheetN", "", 0), "sheet SheetN is not exist")
} }
func TestAddVBAProject(t *testing.T) {
f := NewFile()
assert.NoError(t, f.SetSheetPrOptions("Sheet1", CodeName("Sheet1")))
assert.EqualError(t, f.AddVBAProject("macros.bin"), "stat macros.bin: no such file or directory")
assert.EqualError(t, f.AddVBAProject(filepath.Join("test", "Book1.xlsx")), "unsupported VBA project extension")
assert.NoError(t, f.AddVBAProject(filepath.Join("test", "vbaProject.bin")))
// Test add VBA project twice.
assert.NoError(t, f.AddVBAProject(filepath.Join("test", "vbaProject.bin")))
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddVBAProject.xlsm")))
}
func prepareTestBook1() (*File, error) { func prepareTestBook1() (*File, error) {
f, err := OpenFile(filepath.Join("test", "Book1.xlsx")) f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
if err != nil { if err != nil {

BIN
test/vbaProject.bin Executable file

Binary file not shown.

View File

@ -22,6 +22,7 @@ const (
SourceRelationshipDrawingVML = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing" SourceRelationshipDrawingVML = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing"
SourceRelationshipHyperLink = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" SourceRelationshipHyperLink = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
SourceRelationshipWorkSheet = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" SourceRelationshipWorkSheet = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"
SourceRelationshipVBAProject = "http://schemas.microsoft.com/office/2006/relationships/vbaProject"
SourceRelationshipChart201506 = "http://schemas.microsoft.com/office/drawing/2015/06/chart" SourceRelationshipChart201506 = "http://schemas.microsoft.com/office/drawing/2015/06/chart"
SourceRelationshipChart20070802 = "http://schemas.microsoft.com/office/drawing/2007/8/2/chart" SourceRelationshipChart20070802 = "http://schemas.microsoft.com/office/drawing/2007/8/2/chart"
SourceRelationshipChart2014 = "http://schemas.microsoft.com/office/drawing/2014/chart" SourceRelationshipChart2014 = "http://schemas.microsoft.com/office/drawing/2014/chart"