summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxuri <xuri.me@gmail.com>2018-09-01 23:48:00 +0800
committerGitHub <noreply@github.com>2018-09-01 23:48:00 +0800
commitb691e617d00589f5af3f14f62c61e576254d16c3 (patch)
tree25d8c0a6e3cd1cf5a682ae680a4b7b4222c51ce0
parentce5b37a4ac93196f90cfef2aec381a9b7d153fdd (diff)
parentba459dc659720d7504e5eb6f5bda9081a452a509 (diff)
Merge pull request #267 from rentiansheng/valiationdata, this closes #147 and closes #240.
Initialize data validation support
-rw-r--r--datavalidation.go203
-rw-r--r--datavalidation_test.go32
-rw-r--r--xmlWorksheet.go31
3 files changed, 260 insertions, 6 deletions
diff --git a/datavalidation.go b/datavalidation.go
new file mode 100644
index 0000000..62d2cf8
--- /dev/null
+++ b/datavalidation.go
@@ -0,0 +1,203 @@
+package excelize
+
+import (
+ "fmt"
+ "strings"
+)
+
+// DataValidationType defined the type of data validation.
+type DataValidationType int
+
+// Data validation types.
+const (
+ _DataValidationType = iota
+ typeNone // inline use
+ DataValidationTypeCustom
+ DataValidationTypeDate
+ DataValidationTypeDecimal
+ typeList // inline use
+ DataValidationTypeTextLeng
+ DataValidationTypeTime
+ // DataValidationTypeWhole Integer
+ DataValidationTypeWhole
+)
+
+const (
+ // dataValidationFormulaStrLen 255 characters+ 2 quotes
+ dataValidationFormulaStrLen = 257
+ // dataValidationFormulaStrLenErr
+ dataValidationFormulaStrLenErr = "data validation must be 0-255 characters"
+)
+
+// DataValidationErrorStyle defined the style of data validation error alert.
+type DataValidationErrorStyle int
+
+// Data validation error styles.
+const (
+ _ DataValidationErrorStyle = iota
+ DataValidationErrorStyleStop
+ DataValidationErrorStyleWarning
+ DataValidationErrorStyleInformation
+)
+
+// Data validation error styles.
+const (
+ styleStop = "stop"
+ styleWarning = "warning"
+ styleInformation = "information"
+)
+
+// DataValidationOperator operator enum.
+type DataValidationOperator int
+
+// Data validation operators.
+const (
+ _DataValidationOperator = iota
+ DataValidationOperatorBetween
+ DataValidationOperatorEqual
+ DataValidationOperatorGreaterThan
+ DataValidationOperatorGreaterThanOrEqual
+ DataValidationOperatorLessThan
+ DataValidationOperatorLessThanOrEqual
+ DataValidationOperatorNotBetween
+ DataValidationOperatorNotEqual
+)
+
+// NewDataValidation return data validation struct.
+func NewDataValidation(allowBlank bool) *DataValidation {
+ return &DataValidation{
+ AllowBlank: allowBlank,
+ ShowErrorMessage: false,
+ ShowInputMessage: false,
+ }
+}
+
+// SetError set error notice.
+func (dd *DataValidation) SetError(style DataValidationErrorStyle, title, msg string) {
+ dd.Error = &msg
+ dd.ErrorTitle = &title
+ strStyle := styleStop
+ switch style {
+ case DataValidationErrorStyleStop:
+ strStyle = styleStop
+ case DataValidationErrorStyleWarning:
+ strStyle = styleWarning
+ case DataValidationErrorStyleInformation:
+ strStyle = styleInformation
+
+ }
+ dd.ShowErrorMessage = true
+ dd.ErrorStyle = &strStyle
+}
+
+// SetInput set prompt notice.
+func (dd *DataValidation) SetInput(title, msg string) {
+ dd.ShowInputMessage = true
+ dd.PromptTitle = &title
+ dd.Prompt = &msg
+}
+
+// SetDropList data validation list.
+func (dd *DataValidation) SetDropList(keys []string) error {
+ dd.Formula1 = "\"" + strings.Join(keys, ",") + "\""
+ dd.Type = convDataValidationType(typeList)
+ return nil
+}
+
+// SetRange provides function to set data validation range in drop list.
+func (dd *DataValidation) SetRange(f1, f2 int, t DataValidationType, o DataValidationOperator) error {
+ formula1 := fmt.Sprintf("%d", f1)
+ formula2 := fmt.Sprintf("%d", f2)
+ if dataValidationFormulaStrLen < len(dd.Formula1) || dataValidationFormulaStrLen < len(dd.Formula2) {
+ return fmt.Errorf(dataValidationFormulaStrLenErr)
+ }
+
+ dd.Formula1 = formula1
+ dd.Formula2 = formula2
+ dd.Type = convDataValidationType(t)
+ dd.Operator = convDataValidationOperatior(o)
+ return nil
+}
+
+// SetSqref provides function to set data validation range in drop list.
+func (dd *DataValidation) SetSqref(sqref string) {
+ if dd.Sqref == "" {
+ dd.Sqref = sqref
+ } else {
+ dd.Sqref = fmt.Sprintf("%s %s", dd.Sqref, sqref)
+ }
+}
+
+// convDataValidationType get excel data validation type.
+func convDataValidationType(t DataValidationType) string {
+ typeMap := map[DataValidationType]string{
+ typeNone: "none",
+ DataValidationTypeCustom: "custom",
+ DataValidationTypeDate: "date",
+ DataValidationTypeDecimal: "decimal",
+ typeList: "list",
+ DataValidationTypeTextLeng: "textLength",
+ DataValidationTypeTime: "time",
+ DataValidationTypeWhole: "whole",
+ }
+
+ return typeMap[t]
+
+}
+
+// convDataValidationOperatior get excel data validation operator.
+func convDataValidationOperatior(o DataValidationOperator) string {
+ typeMap := map[DataValidationOperator]string{
+ DataValidationOperatorBetween: "between",
+ DataValidationOperatorEqual: "equal",
+ DataValidationOperatorGreaterThan: "greaterThan",
+ DataValidationOperatorGreaterThanOrEqual: "greaterThanOrEqual",
+ DataValidationOperatorLessThan: "lessThan",
+ DataValidationOperatorLessThanOrEqual: "lessThanOrEqual",
+ DataValidationOperatorNotBetween: "notBetween",
+ DataValidationOperatorNotEqual: "notEqual",
+ }
+
+ return typeMap[o]
+
+}
+
+// AddDataValidation provides set data validation on a range of the worksheet
+// by given data validation object and worksheet name. The data validation
+// object can be created by NewDataValidation function.
+//
+// Example 1, set data validation on Sheet1!A1:B2 with validation criteria
+// settings, show error alert after invalid data is entered whth "Stop" style
+// and custom title "error body":
+//
+// dvRange := excelize.NewDataValidation(true)
+// dvRange.Sqref = "A1:B2"
+// dvRange.SetRange(10, 20, excelize.DataValidationTypeWhole, excelize.DataValidationOperatorBetween)
+// dvRange.SetError(excelize.DataValidationErrorStyleStop, "error title", "error body")
+// xlsx.AddDataValidation("Sheet1", dvRange)
+//
+// Example 2, set data validation on Sheet1!A3:B4 with validation criteria
+// settings, and show input message when cell is selected:
+//
+// dvRange = excelize.NewDataValidation(true)
+// dvRange.Sqref = "A3:B4"
+// dvRange.SetRange(10, 20, excelize.DataValidationTypeWhole, excelize.DataValidationOperatorGreaterThan)
+// dvRange.SetInput("input title", "input body")
+// xlsx.AddDataValidation("Sheet1", dvRange)
+//
+// Example 4, set data validation on Sheet1!A5:B6 with validation criteria
+// settings, create in-cell dropdown by allow list source:
+//
+// dvRange = excelize.NewDataValidation(true)
+// dvRange.Sqref = "A5:B6"
+// dvRange.SetDropList([]string{"1", "2", "3"})
+// xlsx.AddDataValidation("Sheet1", dvRange)
+//
+func (f *File) AddDataValidation(sheet string, dv *DataValidation) {
+ xlsx := f.workSheetReader(sheet)
+ if nil == xlsx.DataValidations {
+ xlsx.DataValidations = new(xlsxDataValidations)
+ }
+ xlsx.DataValidations.DataValidation = append(xlsx.DataValidations.DataValidation, dv)
+ xlsx.DataValidations.Count = len(xlsx.DataValidations.DataValidation)
+}
diff --git a/datavalidation_test.go b/datavalidation_test.go
new file mode 100644
index 0000000..718131f
--- /dev/null
+++ b/datavalidation_test.go
@@ -0,0 +1,32 @@
+package excelize
+
+import (
+ "testing"
+)
+
+func TestDataValidation(t *testing.T) {
+ xlsx := NewFile()
+
+ dvRange := NewDataValidation(true)
+ dvRange.Sqref = "A1:B2"
+ dvRange.SetRange(10, 20, DataValidationTypeWhole, DataValidationOperatorBetween)
+ dvRange.SetError(DataValidationErrorStyleStop, "error title", "error body")
+ xlsx.AddDataValidation("Sheet1", dvRange)
+
+ dvRange = NewDataValidation(true)
+ dvRange.Sqref = "A3:B4"
+ dvRange.SetRange(10, 20, DataValidationTypeWhole, DataValidationOperatorGreaterThan)
+ dvRange.SetInput("input title", "input body")
+ xlsx.AddDataValidation("Sheet1", dvRange)
+
+ dvRange = NewDataValidation(true)
+ dvRange.Sqref = "A5:B6"
+ dvRange.SetDropList([]string{"1", "2", "3"})
+ xlsx.AddDataValidation("Sheet1", dvRange)
+
+ // Test write file to given path.
+ err := xlsx.SaveAs("./test/Bookdatavalition.xlsx")
+ if err != nil {
+ t.Error(err)
+ }
+}
diff --git a/xmlWorksheet.go b/xmlWorksheet.go
index 87d66a1..7cf4994 100644
--- a/xmlWorksheet.go
+++ b/xmlWorksheet.go
@@ -18,7 +18,7 @@ type xlsxWorksheet struct {
MergeCells *xlsxMergeCells `xml:"mergeCells"`
PhoneticPr *xlsxPhoneticPr `xml:"phoneticPr"`
ConditionalFormatting []*xlsxConditionalFormatting `xml:"conditionalFormatting"`
- DataValidations *xlsxDataValidations `xml:"dataValidations"`
+ DataValidations *xlsxDataValidations `xml:"dataValidations,omitempty"`
Hyperlinks *xlsxHyperlinks `xml:"hyperlinks"`
PrintOptions *xlsxPrintOptions `xml:"printOptions"`
PageMargins *xlsxPageMargins `xml:"pageMargins"`
@@ -294,11 +294,30 @@ type xlsxMergeCells struct {
// xlsxDataValidations expresses all data validation information for cells in a
// sheet which have data validation features applied.
type xlsxDataValidations struct {
- Count int `xml:"count,attr,omitempty"`
- DisablePrompts bool `xml:"disablePrompts,attr,omitempty"`
- XWindow int `xml:"xWindow,attr,omitempty"`
- YWindow int `xml:"yWindow,attr,omitempty"`
- DataValidation string `xml:",innerxml"`
+ Count int `xml:"count,attr,omitempty"`
+ DisablePrompts bool `xml:"disablePrompts,attr,omitempty"`
+ XWindow int `xml:"xWindow,attr,omitempty"`
+ YWindow int `xml:"yWindow,attr,omitempty"`
+ DataValidation []*DataValidation `xml:"dataValidation"`
+}
+
+// DataValidation directly maps the a single item of data validation defined
+// on a range of the worksheet.
+type DataValidation struct {
+ AllowBlank bool `xml:"allowBlank,attr"`
+ Error *string `xml:"error,attr"`
+ ErrorStyle *string `xml:"errorStyle,attr"`
+ ErrorTitle *string `xml:"errorTitle,attr"`
+ Operator string `xml:"operator,attr"`
+ Prompt *string `xml:"prompt,attr"`
+ PromptTitle *string `xml:"promptTitle"`
+ ShowDropDown bool `xml:"showDropDown,attr"`
+ ShowErrorMessage bool `xml:"showErrorMessage,attr"`
+ ShowInputMessage bool `xml:"showInputMessage,attr"`
+ Sqref string `xml:"sqref,attr"`
+ Type string `xml:"type,attr"`
+ Formula1 string `xml:"formula1"`
+ Formula2 string `xml:"formula2"`
}
// xlsxC directly maps the c element in the namespace