|  |  |  | @ -19,7 +19,9 @@ import ( | 
			
		
	
		
			
				
					|  |  |  |  | 	"io" | 
			
		
	
		
			
				
					|  |  |  |  | 	"io/ioutil" | 
			
		
	
		
			
				
					|  |  |  |  | 	"os" | 
			
		
	
		
			
				
					|  |  |  |  | 	"path" | 
			
		
	
		
			
				
					|  |  |  |  | 	"strconv" | 
			
		
	
		
			
				
					|  |  |  |  | 	"strings" | 
			
		
	
		
			
				
					|  |  |  |  | ) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // File define a populated XLSX file struct.
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -226,3 +228,78 @@ func (f *File) UpdateLinkedValue() error { | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	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", | 
			
		
	
		
			
				
					|  |  |  |  | 		}) | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
	
		
			
				
					|  |  |  | 
 |