From 656c16f9a8e72c40db7435f4868b18cf22554099 Mon Sep 17 00:00:00 2001
From: xuri <xuri.me@gmail.com>
Date: Tue, 8 Feb 2022 00:08:06 +0800
Subject: [PATCH] This closes #1139, `SetCellDefault` support non-numeric value

- Add default value on getting `View` property of sheet views
- Add examples and unit test for set sheet views
- Re-order field on sheet view options
- Fix incorrect build-in number format: 42
- Simplify code for the `stylesReader` function
---
 cell.go           |   3 +
 sheetview.go      | 153 +++++++++++++++++++++++-----------------------
 sheetview_test.go |  84 ++++++++++++++++---------
 styles.go         |   7 +--
 4 files changed, 136 insertions(+), 111 deletions(-)

diff --git a/cell.go b/cell.go
index 35060ab4e4..9af93f6356 100644
--- a/cell.go
+++ b/cell.go
@@ -450,6 +450,9 @@ func (f *File) SetCellDefault(sheet, axis, value string) error {
 // setCellDefault prepares cell type and string type cell value by a given
 // string.
 func setCellDefault(value string) (t string, v string) {
+	if ok, _ := isNumeric(value); !ok {
+		t = "str"
+	}
 	v = value
 	return
 }
diff --git a/sheetview.go b/sheetview.go
index 5bb5aaff75..b0912ec7a7 100644
--- a/sheetview.go
+++ b/sheetview.go
@@ -27,74 +27,49 @@ type SheetViewOptionPtr interface {
 }
 
 type (
-	// DefaultGridColor is a SheetViewOption. It specifies a flag indicating that
-	// the consuming application should use the default grid lines color (system
-	// dependent). Overrides any color specified in colorId.
+	// DefaultGridColor is a SheetViewOption. It specifies a flag indicating
+	// that the consuming application should use the default grid lines color
+	// (system dependent). Overrides any color specified in colorId.
 	DefaultGridColor bool
-	// RightToLeft is a SheetViewOption. It specifies a flag indicating whether
-	// the sheet is in 'right to left' display mode. When in this mode, Column A
-	// is on the far right, Column B ;is one column left of Column A, and so on.
-	// Also, information in cells is displayed in the Right to Left format.
-	RightToLeft bool
-	// ShowFormulas is a SheetViewOption. It specifies a flag indicating whether
-	// this sheet should display formulas.
+	// ShowFormulas is a SheetViewOption. It specifies a flag indicating
+	// whether this sheet should display formulas.
 	ShowFormulas bool
-	// ShowGridLines is a SheetViewOption. It specifies a flag indicating whether
-	// this sheet should display gridlines.
+	// ShowGridLines is a SheetViewOption. It specifies a flag indicating
+	// whether this sheet should display gridlines.
 	ShowGridLines bool
 	// ShowRowColHeaders is a SheetViewOption. It specifies a flag indicating
 	// whether the sheet should display row and column headings.
 	ShowRowColHeaders bool
-	// ZoomScale is a SheetViewOption. It specifies a window zoom magnification
-	// for current view representing percent values. This attribute is restricted
-	// to values ranging from 10 to 400. Horizontal & Vertical scale together.
-	ZoomScale float64
-	// TopLeftCell is a SheetViewOption. It specifies a location of the top left
-	// visible cell Location of the top left visible cell in the bottom right
-	// pane (when in Left-to-Right mode).
-	TopLeftCell string
-	// ShowZeros is a SheetViewOption. It specifies a flag indicating
-	// whether to "show a zero in cells that have zero value".
-	// When using a formula to reference another cell which is empty, the referenced value becomes 0
+	// ShowZeros is a SheetViewOption. It specifies a flag indicating whether
+	// to "show a zero in cells that have zero value". When using a formula to
+	// reference another cell which is empty, the referenced value becomes 0
 	// when the flag is true. (Default setting is true.)
 	ShowZeros bool
-	// View is a SheetViewOption. It specifies a flag indicating
-	// how sheet is displayed, by default it uses empty string
-	// available options: normal, pageLayout, pageBreakPreview
-	View string
-	// ShowRuler is a SheetViewOption. It specifies a flag indicating
-	// this sheet should display ruler.
+	// RightToLeft is a SheetViewOption. It specifies a flag indicating whether
+	// the sheet is in 'right to left' display mode. When in this mode, Column
+	// A is on the far right, Column B ;is one column left of Column A, and so
+	// on. Also, information in cells is displayed in the Right to Left format.
+	RightToLeft bool
+	// ShowRuler is a SheetViewOption. It specifies a flag indicating this
+	// sheet should display ruler.
 	ShowRuler bool
-
-	/* TODO
-	// ShowWhiteSpace is a SheetViewOption. It specifies a flag indicating
-	// whether page layout view shall display margins. False means do not display
-	// left, right, top (header), and bottom (footer) margins (even when there is
-	// data in the header or footer).
-	ShowWhiteSpace bool
-	// WindowProtection is a SheetViewOption.
-	WindowProtection bool
-	*/
+	// View is a SheetViewOption. It specifies a flag indicating how sheet is
+	// displayed, by default it uses empty string available options: normal,
+	// pageLayout, pageBreakPreview
+	View string
+	// TopLeftCell is a SheetViewOption. It specifies a location of the top
+	// left visible cell Location of the top left visible cell in the bottom
+	// right pane (when in Left-to-Right mode).
+	TopLeftCell string
+	// ZoomScale is a SheetViewOption. It specifies a window zoom magnification
+	// for current view representing percent values. This attribute is
+	// restricted to values ranging from 10 to 400. Horizontal & Vertical
+	// scale together.
+	ZoomScale float64
 )
 
 // Defaults for each option are described in XML schema for CT_SheetView
 
-func (o TopLeftCell) setSheetViewOption(view *xlsxSheetView) {
-	view.TopLeftCell = string(o)
-}
-
-func (o *TopLeftCell) getSheetViewOption(view *xlsxSheetView) {
-	*o = TopLeftCell(string(view.TopLeftCell))
-}
-
-func (o View) setSheetViewOption(view *xlsxSheetView) {
-	view.View = string(o)
-}
-
-func (o *View) getSheetViewOption(view *xlsxSheetView) {
-	*o = View(string(view.View))
-}
-
 func (o DefaultGridColor) setSheetViewOption(view *xlsxSheetView) {
 	view.DefaultGridColor = boolPtr(bool(o))
 }
@@ -103,14 +78,6 @@ func (o *DefaultGridColor) getSheetViewOption(view *xlsxSheetView) {
 	*o = DefaultGridColor(defaultTrue(view.DefaultGridColor)) // Excel default: true
 }
 
-func (o RightToLeft) setSheetViewOption(view *xlsxSheetView) {
-	view.RightToLeft = bool(o) // Excel default: false
-}
-
-func (o *RightToLeft) getSheetViewOption(view *xlsxSheetView) {
-	*o = RightToLeft(view.RightToLeft)
-}
-
 func (o ShowFormulas) setSheetViewOption(view *xlsxSheetView) {
 	view.ShowFormulas = bool(o) // Excel default: false
 }
@@ -127,12 +94,12 @@ func (o *ShowGridLines) getSheetViewOption(view *xlsxSheetView) {
 	*o = ShowGridLines(defaultTrue(view.ShowGridLines)) // Excel default: true
 }
 
-func (o ShowRuler) setSheetViewOption(view *xlsxSheetView) {
-	view.ShowRuler = boolPtr(bool(o))
+func (o ShowRowColHeaders) setSheetViewOption(view *xlsxSheetView) {
+	view.ShowRowColHeaders = boolPtr(bool(o))
 }
 
-func (o *ShowRuler) getSheetViewOption(view *xlsxSheetView) {
-	*o = ShowRuler(defaultTrue(view.ShowRuler)) // Excel default: true
+func (o *ShowRowColHeaders) getSheetViewOption(view *xlsxSheetView) {
+	*o = ShowRowColHeaders(defaultTrue(view.ShowRowColHeaders)) // Excel default: true
 }
 
 func (o ShowZeros) setSheetViewOption(view *xlsxSheetView) {
@@ -143,12 +110,40 @@ func (o *ShowZeros) getSheetViewOption(view *xlsxSheetView) {
 	*o = ShowZeros(defaultTrue(view.ShowZeros)) // Excel default: true
 }
 
-func (o ShowRowColHeaders) setSheetViewOption(view *xlsxSheetView) {
-	view.ShowRowColHeaders = boolPtr(bool(o))
+func (o RightToLeft) setSheetViewOption(view *xlsxSheetView) {
+	view.RightToLeft = bool(o) // Excel default: false
 }
 
-func (o *ShowRowColHeaders) getSheetViewOption(view *xlsxSheetView) {
-	*o = ShowRowColHeaders(defaultTrue(view.ShowRowColHeaders)) // Excel default: true
+func (o *RightToLeft) getSheetViewOption(view *xlsxSheetView) {
+	*o = RightToLeft(view.RightToLeft)
+}
+
+func (o ShowRuler) setSheetViewOption(view *xlsxSheetView) {
+	view.ShowRuler = boolPtr(bool(o))
+}
+
+func (o *ShowRuler) getSheetViewOption(view *xlsxSheetView) {
+	*o = ShowRuler(defaultTrue(view.ShowRuler)) // Excel default: true
+}
+
+func (o View) setSheetViewOption(view *xlsxSheetView) {
+	view.View = string(o)
+}
+
+func (o *View) getSheetViewOption(view *xlsxSheetView) {
+	if view.View != "" {
+		*o = View(view.View)
+		return
+	}
+	*o = View("normal")
+}
+
+func (o TopLeftCell) setSheetViewOption(view *xlsxSheetView) {
+	view.TopLeftCell = string(o)
+}
+
+func (o *TopLeftCell) getSheetViewOption(view *xlsxSheetView) {
+	*o = TopLeftCell(string(view.TopLeftCell))
 }
 
 func (o ZoomScale) setSheetViewOption(view *xlsxSheetView) {
@@ -186,13 +181,15 @@ func (f *File) getSheetView(sheet string, viewIndex int) (*xlsxSheetView, error)
 // Available options:
 //
 //    DefaultGridColor(bool)
-//    RightToLeft(bool)
 //    ShowFormulas(bool)
 //    ShowGridLines(bool)
 //    ShowRowColHeaders(bool)
-//    ZoomScale(float64)
-//    TopLeftCell(string)
 //    ShowZeros(bool)
+//    RightToLeft(bool)
+//    ShowRuler(bool)
+//    View(string)
+//    TopLeftCell(string)
+//    ZoomScale(float64)
 //
 // Example:
 //
@@ -216,13 +213,15 @@ func (f *File) SetSheetViewOptions(name string, viewIndex int, opts ...SheetView
 // Available options:
 //
 //    DefaultGridColor(bool)
-//    RightToLeft(bool)
 //    ShowFormulas(bool)
 //    ShowGridLines(bool)
 //    ShowRowColHeaders(bool)
-//    ZoomScale(float64)
-//    TopLeftCell(string)
 //    ShowZeros(bool)
+//    RightToLeft(bool)
+//    ShowRuler(bool)
+//    View(string)
+//    TopLeftCell(string)
+//    ZoomScale(float64)
 //
 // Example:
 //
diff --git a/sheetview_test.go b/sheetview_test.go
index cfe628d716..2bba8f9802 100644
--- a/sheetview_test.go
+++ b/sheetview_test.go
@@ -9,31 +9,39 @@ import (
 
 var _ = []SheetViewOption{
 	DefaultGridColor(true),
-	RightToLeft(false),
 	ShowFormulas(false),
 	ShowGridLines(true),
 	ShowRowColHeaders(true),
-	TopLeftCell("B2"),
-	View("pageLayout"),
+	ShowZeros(true),
+	RightToLeft(false),
 	ShowRuler(false),
+	View("pageLayout"),
+	TopLeftCell("B2"),
+	ZoomScale(100),
 	// SheetViewOptionPtr are also SheetViewOption
 	new(DefaultGridColor),
-	new(RightToLeft),
 	new(ShowFormulas),
 	new(ShowGridLines),
 	new(ShowRowColHeaders),
+	new(ShowZeros),
+	new(RightToLeft),
+	new(ShowRuler),
+	new(View),
 	new(TopLeftCell),
+	new(ZoomScale),
 }
 
 var _ = []SheetViewOptionPtr{
 	(*DefaultGridColor)(nil),
-	(*RightToLeft)(nil),
 	(*ShowFormulas)(nil),
 	(*ShowGridLines)(nil),
 	(*ShowRowColHeaders)(nil),
-	(*TopLeftCell)(nil),
-	(*View)(nil),
+	(*ShowZeros)(nil),
+	(*RightToLeft)(nil),
 	(*ShowRuler)(nil),
+	(*View)(nil),
+	(*TopLeftCell)(nil),
+	(*ZoomScale)(nil),
 }
 
 func ExampleFile_SetSheetViewOptions() {
@@ -42,14 +50,14 @@ func ExampleFile_SetSheetViewOptions() {
 
 	if err := f.SetSheetViewOptions(sheet, 0,
 		DefaultGridColor(false),
-		RightToLeft(false),
 		ShowFormulas(true),
 		ShowGridLines(true),
 		ShowRowColHeaders(true),
-		ZoomScale(80),
-		TopLeftCell("C3"),
-		View("pageLayout"),
+		RightToLeft(false),
 		ShowRuler(false),
+		View("pageLayout"),
+		TopLeftCell("C3"),
+		ZoomScale(80),
 	); err != nil {
 		fmt.Println(err)
 	}
@@ -95,80 +103,98 @@ func ExampleFile_GetSheetViewOptions() {
 
 	var (
 		defaultGridColor  DefaultGridColor
-		rightToLeft       RightToLeft
 		showFormulas      ShowFormulas
 		showGridLines     ShowGridLines
-		showZeros         ShowZeros
 		showRowColHeaders ShowRowColHeaders
-		zoomScale         ZoomScale
+		showZeros         ShowZeros
+		rightToLeft       RightToLeft
+		showRuler         ShowRuler
+		view              View
 		topLeftCell       TopLeftCell
+		zoomScale         ZoomScale
 	)
 
 	if err := f.GetSheetViewOptions(sheet, 0,
 		&defaultGridColor,
-		&rightToLeft,
 		&showFormulas,
 		&showGridLines,
-		&showZeros,
 		&showRowColHeaders,
-		&zoomScale,
+		&showZeros,
+		&rightToLeft,
+		&showRuler,
+		&view,
 		&topLeftCell,
+		&zoomScale,
 	); err != nil {
 		fmt.Println(err)
 	}
 
 	fmt.Println("Default:")
 	fmt.Println("- defaultGridColor:", defaultGridColor)
-	fmt.Println("- rightToLeft:", rightToLeft)
 	fmt.Println("- showFormulas:", showFormulas)
 	fmt.Println("- showGridLines:", showGridLines)
-	fmt.Println("- showZeros:", showZeros)
 	fmt.Println("- showRowColHeaders:", showRowColHeaders)
-	fmt.Println("- zoomScale:", zoomScale)
+	fmt.Println("- showZeros:", showZeros)
+	fmt.Println("- rightToLeft:", rightToLeft)
+	fmt.Println("- showRuler:", showRuler)
+	fmt.Println("- view:", view)
 	fmt.Println("- topLeftCell:", `"`+topLeftCell+`"`)
+	fmt.Println("- zoomScale:", zoomScale)
 
-	if err := f.SetSheetViewOptions(sheet, 0, TopLeftCell("B2")); err != nil {
+	if err := f.SetSheetViewOptions(sheet, 0, ShowGridLines(false)); err != nil {
 		fmt.Println(err)
 	}
 
-	if err := f.GetSheetViewOptions(sheet, 0, &topLeftCell); err != nil {
+	if err := f.GetSheetViewOptions(sheet, 0, &showGridLines); err != nil {
 		fmt.Println(err)
 	}
 
-	if err := f.SetSheetViewOptions(sheet, 0, ShowGridLines(false)); err != nil {
+	if err := f.SetSheetViewOptions(sheet, 0, ShowZeros(false)); err != nil {
 		fmt.Println(err)
 	}
 
-	if err := f.GetSheetViewOptions(sheet, 0, &showGridLines); err != nil {
+	if err := f.GetSheetViewOptions(sheet, 0, &showZeros); err != nil {
 		fmt.Println(err)
 	}
 
-	if err := f.SetSheetViewOptions(sheet, 0, ShowZeros(false)); err != nil {
+	if err := f.SetSheetViewOptions(sheet, 0, View("pageLayout")); err != nil {
 		fmt.Println(err)
 	}
 
-	if err := f.GetSheetViewOptions(sheet, 0, &showZeros); err != nil {
+	if err := f.GetSheetViewOptions(sheet, 0, &view); err != nil {
+		fmt.Println(err)
+	}
+
+	if err := f.SetSheetViewOptions(sheet, 0, TopLeftCell("B2")); err != nil {
+		fmt.Println(err)
+	}
+
+	if err := f.GetSheetViewOptions(sheet, 0, &topLeftCell); err != nil {
 		fmt.Println(err)
 	}
 
 	fmt.Println("After change:")
 	fmt.Println("- showGridLines:", showGridLines)
 	fmt.Println("- showZeros:", showZeros)
+	fmt.Println("- view:", view)
 	fmt.Println("- topLeftCell:", topLeftCell)
 
 	// Output:
 	// Default:
 	// - defaultGridColor: true
-	// - rightToLeft: false
 	// - showFormulas: false
 	// - showGridLines: true
-	// - showZeros: true
 	// - showRowColHeaders: true
-	// - zoomScale: 0
+	// - showZeros: true
+	// - rightToLeft: false
+	// - showRuler: true
+	// - view: normal
 	// - topLeftCell: ""
+	// - zoomScale: 0
 	// After change:
 	// - showGridLines: false
 	// - showZeros: false
+	// - view: pageLayout
 	// - topLeftCell: B2
 }
 
diff --git a/styles.go b/styles.go
index 5d373d38df..7678b847b3 100644
--- a/styles.go
+++ b/styles.go
@@ -53,7 +53,7 @@ var builtInNumFmt = map[int]string{
 	39: "#,##0.00;(#,##0.00)",
 	40: "#,##0.00;[red](#,##0.00)",
 	41: `_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)`,
-	42: `_("$"* #,##0_);_("$* \(#,##0\);_("$"* "-"_);_(@_)`,
+	42: `_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_)`,
 	43: `_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)`,
 	44: `_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)`,
 	45: "mm:ss",
@@ -1074,16 +1074,13 @@ func is12HourTime(format string) bool {
 // stylesReader provides a function to get the pointer to the structure after
 // deserialization of xl/styles.xml.
 func (f *File) stylesReader() *xlsxStyleSheet {
-	var err error
-
 	if f.Styles == nil {
 		f.Styles = new(xlsxStyleSheet)
-		if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathStyles)))).
+		if err := f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathStyles)))).
 			Decode(f.Styles); err != nil && err != io.EOF {
 			log.Printf("xml decode error: %s", err)
 		}
 	}
-
 	return f.Styles
 }