@@ -390,7 +390,7 @@ func (f *File) DeleteFormControl(sheet, cell string) error {
390390 VPath : & vPath {GradientShapeOK : "t" , ConnectType : "rect" },
391391 },
392392 }
393- // load exist VML shapes from xl/drawings/vmlDrawing%d.vml
393+ // Load exist VML shapes from xl/drawings/vmlDrawing%d.vml
394394 d , err := f .decodeVMLDrawingReader (drawingVML )
395395 if err != nil {
396396 return err
@@ -477,7 +477,7 @@ func (f *File) vmlDrawingWriter() {
477477// addVMLObject provides a function to create VML drawing parts and
478478// relationships for comments and form controls.
479479func (f * File ) addVMLObject (opts vmlOptions ) error {
480- // Read sheet data.
480+ // Read sheet data
481481 ws , err := f .workSheetReader (opts .sheet )
482482 if err != nil {
483483 return err
@@ -836,7 +836,7 @@ func (f *File) addDrawingVML(dataID int, drawingVML string, opts *vmlOptions) er
836836 VPath : & vPath {GradientShapeOK : "t" , ConnectType : "rect" },
837837 },
838838 }
839- // load exist VML shapes from xl/drawings/vmlDrawing%d.vml
839+ // Load exist VML shapes from xl/drawings/vmlDrawing%d.vml
840840 d , err := f .decodeVMLDrawingReader (drawingVML )
841841 if err != nil {
842842 return err
@@ -883,3 +883,87 @@ func (f *File) addDrawingVML(dataID int, drawingVML string, opts *vmlOptions) er
883883 f .VMLDrawing [drawingVML ] = vml
884884 return err
885885}
886+
887+ // GetFormControls retrieves all form controls in a worksheet by a given
888+ // worksheet name. Note that, this function does not support getting the width,
889+ // height, text, rich text, and format currently.
890+ func (f * File ) GetFormControls (sheet string ) ([]FormControl , error ) {
891+ var formControls []FormControl
892+ // Read sheet data
893+ ws , err := f .workSheetReader (sheet )
894+ if err != nil {
895+ return formControls , err
896+ }
897+ if ws .LegacyDrawing == nil {
898+ return formControls , err
899+ }
900+ target := f .getSheetRelationshipsTargetByID (sheet , ws .LegacyDrawing .RID )
901+ drawingVML := strings .ReplaceAll (target , ".." , "xl" )
902+ vml := f .VMLDrawing [drawingVML ]
903+ if vml == nil {
904+ // Load exist VML shapes from xl/drawings/vmlDrawing%d.vml
905+ d , err := f .decodeVMLDrawingReader (drawingVML )
906+ if err != nil {
907+ return formControls , err
908+ }
909+ for _ , sp := range d .Shape {
910+ if sp .Type != "#_x0000_t201" {
911+ continue
912+ }
913+ formControl , err := extractFormControl (sp .Val )
914+ if err != nil {
915+ return formControls , err
916+ }
917+ if formControl .Type == FormControlNote || formControl .Cell == "" {
918+ continue
919+ }
920+ formControls = append (formControls , formControl )
921+ }
922+ return formControls , err
923+ }
924+ for _ , sp := range vml .Shape {
925+ if sp .Type != "#_x0000_t201" {
926+ continue
927+ }
928+ formControl , err := extractFormControl (sp .Val )
929+ if err != nil {
930+ return formControls , err
931+ }
932+ if formControl .Type == FormControlNote || formControl .Cell == "" {
933+ continue
934+ }
935+ formControls = append (formControls , formControl )
936+ }
937+ return formControls , err
938+ }
939+
940+ // extractFormControl provides a function to extract form controls for a
941+ // worksheets by given client data.
942+ func extractFormControl (clientData string ) (FormControl , error ) {
943+ var (
944+ err error
945+ formControl FormControl
946+ shapeVal decodeShapeVal
947+ )
948+ if err = xml .Unmarshal ([]byte (fmt .Sprintf ("<shape>%s</shape>" , clientData )), & shapeVal ); err != nil {
949+ return formControl , err
950+ }
951+ for formCtrlType , preset := range formCtrlPresets {
952+ if shapeVal .ClientData .ObjectType == preset .objectType {
953+ formControl .Type = formCtrlType
954+ if formControl .Cell , err = CoordinatesToCellName (shapeVal .ClientData .Column + 1 , shapeVal .ClientData .Row + 1 ); err != nil {
955+ return formControl , err
956+ }
957+ formControl .Macro = shapeVal .ClientData .FmlaMacro
958+ formControl .Checked = shapeVal .ClientData .Checked != 0
959+ formControl .CellLink = shapeVal .ClientData .FmlaLink
960+ formControl .CurrentVal = shapeVal .ClientData .Val
961+ formControl .MinVal = shapeVal .ClientData .Min
962+ formControl .MaxVal = shapeVal .ClientData .Max
963+ formControl .IncChange = shapeVal .ClientData .Inc
964+ formControl .PageChange = shapeVal .ClientData .Page
965+ formControl .Horizontally = shapeVal .ClientData .Horiz != nil
966+ }
967+ }
968+ return formControl , err
969+ }
0 commit comments