Browse Source

support multiple datavalidation role issue #10

rentiansheng 7 years ago
parent
commit
d26da2e188
5 changed files with 142 additions and 57 deletions
  1. 51 29
      col.go
  2. 41 0
      datavalidation_test.go
  3. 29 18
      lib.go
  4. 9 2
      sheet.go
  5. 12 8
      xmlWorksheet.go

+ 51 - 29
col.go

@@ -6,18 +6,16 @@ const Excel2006MaxRowIndex = 1048576
 const Excel2006MinRowIndex = 1
 const Excel2006MinRowIndex = 1
 
 
 type Col struct {
 type Col struct {
-	Min                 int
-	Max                 int
-	Hidden              bool
-	Width               float64
-	Collapsed           bool
-	OutlineLevel        uint8
-	numFmt              string
-	parsedNumFmt        *parsedNumberFormat
-	style               *Style
-	DataValidation      *xlsxCellDataValidation
-	DataValidationStart int
-	DataValidationEnd   int
+	Min            int
+	Max            int
+	Hidden         bool
+	Width          float64
+	Collapsed      bool
+	OutlineLevel   uint8
+	numFmt         string
+	parsedNumFmt   *parsedNumberFormat
+	style          *Style
+	DataValidation []*xlsxCellDataValidation
 }
 }
 
 
 // SetType will set the format string of a column based on the type that you want to set it to.
 // SetType will set the format string of a column based on the type that you want to set it to.
@@ -55,32 +53,56 @@ func (c *Col) SetStyle(style *Style) {
 
 
 // SetDataValidation set data validation with start,end ; start or end  = 0  equal all column
 // SetDataValidation set data validation with start,end ; start or end  = 0  equal all column
 func (c *Col) SetDataValidation(dd *xlsxCellDataValidation, start, end int) {
 func (c *Col) SetDataValidation(dd *xlsxCellDataValidation, start, end int) {
-	//2006 excel all row 1048576
+
 	if 0 == start {
 	if 0 == start {
-		c.DataValidationStart = Excel2006MinRowIndex
+		start = Excel2006MinRowIndex
 	} else {
 	} else {
-		c.DataValidationStart = start
+		start = start + 1
 	}
 	}
 
 
-	if 0 == end || c.DataValidationEnd > Excel2006MaxRowIndex {
-		c.DataValidationEnd = Excel2006MaxRowIndex
-	} else {
-		c.DataValidationEnd = end
+	if 0 == end {
+		end = Excel2006MinRowIndex
+	} else if end < Excel2006MaxRowIndex {
+		end = end + 1
 	}
 	}
-	c.DataValidation = dd
+
+	dd.minRow = start
+	dd.maxRow = end
+
+	tmpDD := make([]*xlsxCellDataValidation, 0)
+	for _, item := range c.DataValidation {
+		if item.maxRow < dd.minRow {
+			tmpDD = append(tmpDD, item) //No intersection
+		} else if item.minRow > dd.maxRow {
+			tmpDD = append(tmpDD, item) //No intersection
+		} else if dd.minRow <= item.minRow && dd.maxRow >= item.maxRow {
+			continue //union , item can be ignored
+		} else if dd.minRow >= item.minRow {
+			//Split into three or two, Newly added object, intersect with the current object in the lower half
+			tmpSplit := new(xlsxCellDataValidation)
+			*tmpSplit = *item
+
+			if dd.minRow > item.minRow { //header whetherneed to split
+				item.maxRow = dd.minRow - 1
+				tmpDD = append(tmpDD, item)
+			}
+			if dd.maxRow < tmpSplit.maxRow { //footer whetherneed to split
+				tmpSplit.minRow = dd.maxRow + 1
+				tmpDD = append(tmpDD, tmpSplit)
+			}
+
+		} else {
+			item.minRow = dd.maxRow + 1
+			tmpDD = append(tmpDD, item)
+		}
+	}
+	tmpDD = append(tmpDD, dd)
+	c.DataValidation = tmpDD
 
 
 }
 }
 
 
 // SetDataValidationWithStart set data validation with start
 // SetDataValidationWithStart set data validation with start
 func (c *Col) SetDataValidationWithStart(dd *xlsxCellDataValidation, start int) {
 func (c *Col) SetDataValidationWithStart(dd *xlsxCellDataValidation, start int) {
 	//2006 excel all row 1048576
 	//2006 excel all row 1048576
-	if 0 == start {
-		c.DataValidationStart = Excel2006MinRowIndex
-	} else {
-		c.DataValidationStart = start
-	}
-
-	c.DataValidationEnd = Excel2006MaxRowIndex
-	c.DataValidation = dd
-
+	c.SetDataValidation(dd, start, Excel2006MaxRowIndex)
 }
 }

+ 41 - 0
datavalidation_test.go

@@ -136,6 +136,47 @@ func TestDataValidation(t *testing.T) {
 		fmt.Printf(err.Error())
 		fmt.Printf(err.Error())
 	}
 	}
 
 
+	dd = NewXlsxCellDataValidation(true, true, true)
+	dd.SetDropList([]string{"1", "2", "4"})
+	dd1 := NewXlsxCellDataValidation(true, true, true)
+	dd1.SetDropList([]string{"11", "22", "44"})
+	dd2 := NewXlsxCellDataValidation(true, true, true)
+	dd2.SetDropList([]string{"111", "222", "444"})
+	sheet.Col(12).SetDataValidation(dd, 2, 10)
+	sheet.Col(12).SetDataValidation(dd1, 3, 4)
+	sheet.Col(12).SetDataValidation(dd2, 5, 7)
+
+	dd = NewXlsxCellDataValidation(true, true, true)
+	dd.SetDropList([]string{"1", "2", "4"})
+	dd1 = NewXlsxCellDataValidation(true, true, true)
+	dd1.SetDropList([]string{"11", "22", "44"})
+	sheet.Col(13).SetDataValidation(dd, 2, 10)
+	sheet.Col(13).SetDataValidation(dd1, 1, 2)
+
+	dd = NewXlsxCellDataValidation(true, true, true)
+	dd.SetDropList([]string{"1", "2", "4"})
+	dd1 = NewXlsxCellDataValidation(true, true, true)
+	dd1.SetDropList([]string{"11", "22", "44"})
+	sheet.Col(14).SetDataValidation(dd, 2, 10)
+	sheet.Col(14).SetDataValidation(dd1, 1, 5)
+
+	dd = NewXlsxCellDataValidation(true, true, true)
+	dd.SetDropList([]string{"1", "2", "4"})
+	dd1 = NewXlsxCellDataValidation(true, true, true)
+	dd1.SetDropList([]string{"11", "22", "44"})
+	sheet.Col(15).SetDataValidation(dd, 2, 10)
+	sheet.Col(15).SetDataValidation(dd1, 1, 10)
+
+	dd = NewXlsxCellDataValidation(true, true, true)
+	dd.SetDropList([]string{"1", "2", "4"})
+	dd1 = NewXlsxCellDataValidation(true, true, true)
+	dd1.SetDropList([]string{"11", "22", "44"})
+	dd2 = NewXlsxCellDataValidation(true, true, true)
+	dd2.SetDropList([]string{"111", "222", "444"})
+	sheet.Col(16).SetDataValidation(dd, 10, 20)
+	sheet.Col(16).SetDataValidation(dd1, 2, 4)
+	sheet.Col(16).SetDataValidation(dd2, 21, 30)
+
 	file.Save("datavalidation.xlsx")
 	file.Save("datavalidation.xlsx")
 
 
 }
 }

+ 29 - 18
lib.go

@@ -701,32 +701,43 @@ func readSheetFromFile(sc chan *indexedSheet, index int, rsheet xlsxSheet, fi *F
 	sheet.SheetFormat.OutlineLevelRow = worksheet.SheetFormatPr.OutlineLevelRow
 	sheet.SheetFormat.OutlineLevelRow = worksheet.SheetFormatPr.OutlineLevelRow
 	if nil != worksheet.DataValidations {
 	if nil != worksheet.DataValidations {
 		for _, dd := range worksheet.DataValidations.DataValidattion {
 		for _, dd := range worksheet.DataValidations.DataValidattion {
+			sqrefArr := strings.Split(dd.Sqref, " ")
+			for _, sqref := range sqrefArr {
+				parts := strings.Split(sqref, ":")
 
 
-			parts := strings.Split(dd.Sqref, ":")
-
-			minCol, minRow, err := GetCoordsFromCellIDString(parts[0])
-			if nil != err {
-				return fmt.Errorf("data validation %s", err.Error())
-			}
-			dd.Sqref = ""
-
-			if 2 == len(parts) {
-				maxCol, maxRow, err := GetCoordsFromCellIDString(parts[1])
+				minCol, minRow, err := GetCoordsFromCellIDString(parts[0])
 				if nil != err {
 				if nil != err {
 					return fmt.Errorf("data validation %s", err.Error())
 					return fmt.Errorf("data validation %s", err.Error())
 				}
 				}
 
 
-				if minCol == maxCol && minRow == maxRow {
-					sheet.Cell(minRow, minCol).SetDataValidation(dd)
-				} else {
-					for i := minCol; i <= maxCol; i++ {
-						sheet.Col(i).SetDataValidation(dd, minRow, maxRow)
+				if 2 == len(parts) {
+					maxCol, maxRow, err := GetCoordsFromCellIDString(parts[1])
+					if nil != err {
+						return fmt.Errorf("data validation %s", err.Error())
 					}
 					}
 
 
-				}
-			} else {
-				sheet.Cell(minRow, minCol).SetDataValidation(dd)
+					if minCol == maxCol && minRow == maxRow {
+						newDD := new(xlsxCellDataValidation)
+						*newDD = *dd
+						newDD.Sqref = ""
+						sheet.Cell(minRow, minCol).SetDataValidation(newDD)
+					} else {
+						// one col mutli dd , error todo
+						for i := minCol; i <= maxCol; i++ {
+							newDD := new(xlsxCellDataValidation)
+							*newDD = *dd
+							newDD.Sqref = ""
+							sheet.Col(i).SetDataValidation(dd, minRow, maxRow)
+						}
+
+					}
+				} else {
+					newDD := new(xlsxCellDataValidation)
+					*newDD = *dd
+					newDD.Sqref = ""
+					sheet.Cell(minRow, minCol).SetDataValidation(dd)
 
 
+				}
 			}
 			}
 
 
 		}
 		}

+ 9 - 2
sheet.go

@@ -253,8 +253,15 @@ func (s *Sheet) makeXLSXSheet(refTable *RefTable, styles *xlsxStyleSheet) *xlsxW
 				worksheet.DataValidations = &xlsxCellDataValidations{}
 				worksheet.DataValidations = &xlsxCellDataValidations{}
 			}
 			}
 			colName := ColIndexToLetters(c)
 			colName := ColIndexToLetters(c)
-			col.DataValidation.Sqref = fmt.Sprintf("%s%d:%s%d", colName, col.DataValidationStart, colName, col.DataValidationEnd)
-			worksheet.DataValidations.DataValidattion = append(worksheet.DataValidations.DataValidattion, col.DataValidation)
+			for _, dd := range col.DataValidation {
+				if dd.minRow == dd.maxRow {
+					dd.Sqref = fmt.Sprintf("%s%d", colName, dd.minRow)
+				} else {
+					dd.Sqref = fmt.Sprintf("%s%d:%s%d", colName, dd.minRow, colName, dd.maxRow)
+				}
+				worksheet.DataValidations.DataValidattion = append(worksheet.DataValidations.DataValidattion, dd)
+
+			}
 			worksheet.DataValidations.Count = len(worksheet.DataValidations.DataValidattion)
 			worksheet.DataValidations.Count = len(worksheet.DataValidations.DataValidattion)
 		}
 		}
 	}
 	}

+ 12 - 8
xmlWorksheet.go

@@ -232,19 +232,23 @@ type xlsxCellDataValidations struct {
 
 
 // xlsxCellDataValidation single data validation
 // xlsxCellDataValidation single data validation
 type xlsxCellDataValidation struct {
 type xlsxCellDataValidation struct {
-	AllowBlank       string  `xml:"allowBlank,attr"`       // allow empty
-	ShowInputMessage string  `xml:"showInputMessage,attr"` // 1, true,0,false,  select cell,  Whether the input message is displayed
-	ShowErrorMessage string  `xml:"showErrorMessage,attr"` // 1, true,0,false,  input error value, Whether the error message is displayed
-	ErrorStyle       *string `xml:"errorStyle,attr"`       //error icon style, warning, infomation,stop
-	ErrorTitle       *string `xml:"errorTitle,attr"`       // error title
-	Operator         string  `xml:"operator,attr"`         //
-	Error            *string `xml:"error,attr"`            // input error value,  notice message
-	PromptTitle      *string `xml:"promptTitle"`
+	AllowBlank       string  `xml:"allowBlank,attr"`         // allow empty
+	ShowInputMessage string  `xml:"showInputMessage,attr"`   // 1, true,0,false,  select cell,  Whether the input message is displayed
+	ShowErrorMessage string  `xml:"showErrorMessage,attr"`   // 1, true,0,false,  input error value, Whether the error message is displayed
+	ErrorStyle       *string `xml:"errorStyle,attr"`         //error icon style, warning, infomation,stop
+	ErrorTitle       *string `xml:"errorTitle,attr"`         // error title
+	Operator         string  `xml:"operator,attr,omitempty"` //
+	Error            *string `xml:"error,attr"`              // input error value,  notice message
+	PromptTitle      *string `xml:"promptTitle,attr"`
 	Prompt           *string `xml:"prompt,attr"`
 	Prompt           *string `xml:"prompt,attr"`
 	Type             string  `xml:"type,attr"`  //data type, none,custom,date,decimal,list, textLength,time,whole
 	Type             string  `xml:"type,attr"`  //data type, none,custom,date,decimal,list, textLength,time,whole
 	Sqref            string  `xml:"sqref,attr"` //Validity of data validation rules, cell and range, eg: A1 OR A1:A20
 	Sqref            string  `xml:"sqref,attr"` //Validity of data validation rules, cell and range, eg: A1 OR A1:A20
 	Formula1         string  `xml:"formula1"`   // data validation role
 	Formula1         string  `xml:"formula1"`   // data validation role
 	Formula2         string  `xml:"formula2"`   //data validation role
 	Formula2         string  `xml:"formula2"`   //data validation role
+	minRow           int     `xml:"-"`
+	maxRow           int     `xml:"-"`
+	//minCol         int     `xml:"-"` //spare
+	//maxCol         int     `xml:"-"` //spare
 }
 }
 
 
 // xlsxRow directly maps the row element in the namespace
 // xlsxRow directly maps the row element in the namespace