未验证 提交 134865d9 编写于 作者: N Nick 提交者: GitHub

Update data validation type and operator's enumerations (#1714)

上级 a0252bd0
......@@ -23,15 +23,14 @@ type DataValidationType int
// Data validation types.
const (
_DataValidationType = iota
typeNone // inline use
_ DataValidationType = iota
DataValidationTypeNone
DataValidationTypeCustom
DataValidationTypeDate
DataValidationTypeDecimal
typeList // inline use
DataValidationTypeList
DataValidationTypeTextLength
DataValidationTypeTime
// DataValidationTypeWhole Integer
DataValidationTypeWhole
)
......@@ -58,7 +57,7 @@ type DataValidationOperator int
// Data validation operators.
const (
_DataValidationOperator = iota
_ DataValidationOperator = iota
DataValidationOperatorBetween
DataValidationOperatorEqual
DataValidationOperatorGreaterThan
......@@ -69,13 +68,42 @@ const (
DataValidationOperatorNotEqual
)
// formulaEscaper mimics the Excel escaping rules for data validation,
// which converts `"` to `""` instead of `"`.
var formulaEscaper = strings.NewReplacer(
`&`, `&`,
`<`, `&lt;`,
`>`, `&gt;`,
`"`, `""`,
var (
// formulaEscaper mimics the Excel escaping rules for data validation,
// which converts `"` to `""` instead of `&quot;`.
formulaEscaper = strings.NewReplacer(
`&`, `&amp;`,
`<`, `&lt;`,
`>`, `&gt;`,
`"`, `""`,
)
// dataValidationTypeMap defined supported data validation types.
dataValidationTypeMap = map[DataValidationType]string{
DataValidationTypeNone: "none",
DataValidationTypeCustom: "custom",
DataValidationTypeDate: "date",
DataValidationTypeDecimal: "decimal",
DataValidationTypeList: "list",
DataValidationTypeTextLength: "textLength",
DataValidationTypeTime: "time",
DataValidationTypeWhole: "whole",
}
// dataValidationOperatorMap defined supported data validation operators.
dataValidationOperatorMap = map[DataValidationOperator]string{
DataValidationOperatorBetween: "between",
DataValidationOperatorEqual: "equal",
DataValidationOperatorGreaterThan: "greaterThan",
DataValidationOperatorGreaterThanOrEqual: "greaterThanOrEqual",
DataValidationOperatorLessThan: "lessThan",
DataValidationOperatorLessThanOrEqual: "lessThanOrEqual",
DataValidationOperatorNotBetween: "notBetween",
DataValidationOperatorNotEqual: "notEqual",
}
)
const (
formula1Name = "formula1"
formula2Name = "formula2"
)
// NewDataValidation return data validation struct.
......@@ -123,45 +151,43 @@ func (dv *DataValidation) SetDropList(keys []string) error {
if MaxFieldLength < len(utf16.Encode([]rune(formula))) {
return ErrDataValidationFormulaLength
}
dv.Formula1 = fmt.Sprintf(`<formula1>"%s"</formula1>`, formulaEscaper.Replace(formula))
dv.Type = convDataValidationType(typeList)
dv.Formula1 = fmt.Sprintf(`<%[2]s>"%[1]s"</%[2]s>`, formulaEscaper.Replace(formula), formula1Name)
dv.Type = dataValidationTypeMap[DataValidationTypeList]
return nil
}
// SetRange provides function to set data validation range in drop list, only
// accepts int, float64, or string data type formula argument.
// accepts int, float64, string or []string data type formula argument.
func (dv *DataValidation) SetRange(f1, f2 interface{}, t DataValidationType, o DataValidationOperator) error {
var formula1, formula2 string
switch v := f1.(type) {
case int:
formula1 = fmt.Sprintf("<formula1>%d</formula1>", v)
case float64:
if math.Abs(v) > math.MaxFloat32 {
return ErrDataValidationRange
genFormula := func(name string, val interface{}) (string, error) {
var formula string
switch v := val.(type) {
case int:
formula = fmt.Sprintf("<%s>%d</%s>", name, v, name)
case float64:
if math.Abs(v) > math.MaxFloat32 {
return formula, ErrDataValidationRange
}
formula = fmt.Sprintf("<%s>%.17g</%s>", name, v, name)
case string:
formula = fmt.Sprintf("<%s>%s</%s>", name, v, name)
default:
return formula, ErrParameterInvalid
}
formula1 = fmt.Sprintf("<formula1>%.17g</formula1>", v)
case string:
formula1 = fmt.Sprintf("<formula1>%s</formula1>", v)
default:
return ErrParameterInvalid
return formula, nil
}
switch v := f2.(type) {
case int:
formula2 = fmt.Sprintf("<formula2>%d</formula2>", v)
case float64:
if math.Abs(v) > math.MaxFloat32 {
return ErrDataValidationRange
}
formula2 = fmt.Sprintf("<formula2>%.17g</formula2>", v)
case string:
formula2 = fmt.Sprintf("<formula2>%s</formula2>", v)
default:
return ErrParameterInvalid
formula1, err := genFormula(formula1Name, f1)
if err != nil {
return err
}
formula2, err := genFormula(formula2Name, f2)
if err != nil {
return err
}
dv.Formula1, dv.Formula2 = formula1, formula2
dv.Type = convDataValidationType(t)
dv.Operator = convDataValidationOperator(o)
return nil
dv.Type = dataValidationTypeMap[t]
dv.Operator = dataValidationOperatorMap[o]
return err
}
// SetSqrefDropList provides set data validation on a range with source
......@@ -180,48 +206,16 @@ func (dv *DataValidation) SetRange(f1, f2 interface{}, t DataValidationType, o D
// err := f.AddDataValidation("Sheet1", dv)
func (dv *DataValidation) SetSqrefDropList(sqref string) {
dv.Formula1 = fmt.Sprintf("<formula1>%s</formula1>", sqref)
dv.Type = convDataValidationType(typeList)
dv.Type = dataValidationTypeMap[DataValidationTypeList]
}
// SetSqref provides function to set data validation range in drop list.
func (dv *DataValidation) SetSqref(sqref string) {
if dv.Sqref == "" {
dv.Sqref = sqref
} else {
dv.Sqref = fmt.Sprintf("%s %s", dv.Sqref, sqref)
return
}
}
// 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",
DataValidationTypeTextLength: "textLength",
DataValidationTypeTime: "time",
DataValidationTypeWhole: "whole",
}
return typeMap[t]
}
// convDataValidationOperator get excel data validation operator.
func convDataValidationOperator(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]
dv.Sqref = fmt.Sprintf("%s %s", dv.Sqref, sqref)
}
// AddDataValidation provides set data validation on a range of the worksheet
......@@ -337,23 +331,23 @@ func (f *File) squashSqref(cells [][]int) []string {
} else if len(cells) == 0 {
return []string{}
}
var res []string
var refs []string
l, r := 0, 0
for i := 1; i < len(cells); i++ {
if cells[i][0] == cells[r][0] && cells[i][1]-cells[r][1] > 1 {
curr, _ := f.coordinatesToRangeRef(append(cells[l], cells[r]...))
ref, _ := f.coordinatesToRangeRef(append(cells[l], cells[r]...))
if l == r {
curr, _ = CoordinatesToCellName(cells[l][0], cells[l][1])
ref, _ = CoordinatesToCellName(cells[l][0], cells[l][1])
}
res = append(res, curr)
refs = append(refs, ref)
l, r = i, i
} else {
r++
}
}
curr, _ := f.coordinatesToRangeRef(append(cells[l], cells[r]...))
ref, _ := f.coordinatesToRangeRef(append(cells[l], cells[r]...))
if l == r {
curr, _ = CoordinatesToCellName(cells[l][0], cells[l][1])
ref, _ = CoordinatesToCellName(cells[l][0], cells[l][1])
}
return append(res, curr)
return append(refs, ref)
}
......@@ -67,6 +67,12 @@ func TestDataValidation(t *testing.T) {
assert.NoError(t, err)
assert.Len(t, dataValidations, 1)
dv = NewDataValidation(true)
dv.Sqref = "A4:A5"
assert.NoError(t, dv.SetRange("Sheet2!$A$2:$A$3", "", DataValidationTypeList, DataValidationOperatorBetween))
dv.SetError(DataValidationErrorStyleStop, "error title", "error body")
assert.NoError(t, f.AddDataValidation("Sheet2", dv))
dv = NewDataValidation(true)
dv.Sqref = "A5:B6"
for _, listValid := range [][]string{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册