rows.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. package excelize
  2. import (
  3. "encoding/xml"
  4. "strconv"
  5. "strings"
  6. )
  7. // GetRows return all the rows in a sheet by given "sheet" + index. For now you
  8. // should use sheet_name like "sheet3" where "sheet" is a constant part and "3"
  9. // is a sheet number. For example, if sheet named as "SomeUniqueData" and it is
  10. // second if spreadsheet program interface - you should use "sheet2" here. For
  11. // example:
  12. //
  13. // index := xlsx.GetSheetIndex("Sheet2")
  14. // rows := xlsx.GetRows("sheet" + strconv.Itoa(index))
  15. // for _, row := range rows {
  16. // for _, colCell := range row {
  17. // fmt.Print(colCell, "\t")
  18. // }
  19. // fmt.Println()
  20. // }
  21. //
  22. func (f *File) GetRows(sheet string) [][]string {
  23. xlsx := f.workSheetReader(sheet)
  24. rows := [][]string{}
  25. name := "xl/worksheets/" + strings.ToLower(sheet) + ".xml"
  26. if xlsx != nil {
  27. output, _ := xml.Marshal(f.Sheet[name])
  28. f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpace(string(output)))
  29. }
  30. decoder := xml.NewDecoder(strings.NewReader(f.readXML(name)))
  31. d := f.sharedStringsReader()
  32. var inElement string
  33. var r xlsxRow
  34. var row []string
  35. tr, tc := f.getTotalRowsCols(sheet)
  36. for i := 0; i < tr; i++ {
  37. row = []string{}
  38. for j := 0; j <= tc; j++ {
  39. row = append(row, "")
  40. }
  41. rows = append(rows, row)
  42. }
  43. decoder = xml.NewDecoder(strings.NewReader(f.readXML(name)))
  44. for {
  45. token, _ := decoder.Token()
  46. if token == nil {
  47. break
  48. }
  49. switch startElement := token.(type) {
  50. case xml.StartElement:
  51. inElement = startElement.Name.Local
  52. if inElement == "row" {
  53. r = xlsxRow{}
  54. decoder.DecodeElement(&r, &startElement)
  55. cr := r.R - 1
  56. for _, colCell := range r.C {
  57. c := TitleToNumber(strings.Map(letterOnlyMapF, colCell.R))
  58. val, _ := colCell.getValueFrom(f, d)
  59. rows[cr][c] = val
  60. }
  61. }
  62. default:
  63. }
  64. }
  65. return rows
  66. }
  67. // getTotalRowsCols provides a function to get total columns and rows in a
  68. // sheet.
  69. func (f *File) getTotalRowsCols(sheet string) (int, int) {
  70. name := "xl/worksheets/" + strings.ToLower(sheet) + ".xml"
  71. decoder := xml.NewDecoder(strings.NewReader(f.readXML(name)))
  72. var inElement string
  73. var r xlsxRow
  74. var tr, tc int
  75. for {
  76. token, _ := decoder.Token()
  77. if token == nil {
  78. break
  79. }
  80. switch startElement := token.(type) {
  81. case xml.StartElement:
  82. inElement = startElement.Name.Local
  83. if inElement == "row" {
  84. r = xlsxRow{}
  85. decoder.DecodeElement(&r, &startElement)
  86. tr = r.R
  87. for _, colCell := range r.C {
  88. col := TitleToNumber(strings.Map(letterOnlyMapF, colCell.R))
  89. if col > tc {
  90. tc = col
  91. }
  92. }
  93. }
  94. default:
  95. }
  96. }
  97. return tr, tc
  98. }
  99. // SetRowHeight provides a function to set the height of a single row.
  100. // For example:
  101. //
  102. // xlsx := excelize.NewFile()
  103. // xlsx.SetRowHeight("Sheet1", 0, 50)
  104. // err := xlsx.Save()
  105. // if err != nil {
  106. // fmt.Println(err)
  107. // os.Exit(1)
  108. // }
  109. //
  110. func (f *File) SetRowHeight(sheet string, rowIndex int, height float64) {
  111. xlsx := f.workSheetReader(sheet)
  112. rows := rowIndex + 1
  113. cells := 0
  114. completeRow(xlsx, rows, cells)
  115. xlsx.SheetData.Row[rowIndex].Ht = height
  116. xlsx.SheetData.Row[rowIndex].CustomHeight = true
  117. }
  118. // getRowHeight provides function to get row height in pixels by given sheet
  119. // name and row index.
  120. func (f *File) getRowHeight(sheet string, row int) int {
  121. xlsx := f.workSheetReader(sheet)
  122. for _, v := range xlsx.SheetData.Row {
  123. if v.R == row+1 && v.Ht != 0 {
  124. return int(convertRowHeightToPixels(v.Ht))
  125. }
  126. }
  127. // Optimisation for when the row heights haven't changed.
  128. return int(defaultRowHeightPixels)
  129. }
  130. // GetRowHeight provides function to get row height by given worksheet name and
  131. // row index.
  132. func (f *File) GetRowHeight(sheet string, row int) float64 {
  133. xlsx := f.workSheetReader(sheet)
  134. for _, v := range xlsx.SheetData.Row {
  135. if v.R == row+1 && v.Ht != 0 {
  136. return v.Ht
  137. }
  138. }
  139. // Optimisation for when the row heights haven't changed.
  140. return defaultRowHeightPixels
  141. }
  142. // sharedStringsReader provides function to get the pointer to the structure
  143. // after deserialization of xl/sharedStrings.xml.
  144. func (f *File) sharedStringsReader() *xlsxSST {
  145. if f.SharedStrings == nil {
  146. var sharedStrings xlsxSST
  147. xml.Unmarshal([]byte(f.readXML("xl/sharedStrings.xml")), &sharedStrings)
  148. f.SharedStrings = &sharedStrings
  149. }
  150. return f.SharedStrings
  151. }
  152. // getValueFrom return a value from a column/row cell, this function is inteded
  153. // to be used with for range on rows an argument with the xlsx opened file.
  154. func (xlsx *xlsxC) getValueFrom(f *File, d *xlsxSST) (string, error) {
  155. switch xlsx.T {
  156. case "s":
  157. xlsxSI := 0
  158. xlsxSI, _ = strconv.Atoi(xlsx.V)
  159. if len(d.SI[xlsxSI].R) > 0 {
  160. value := ""
  161. for _, v := range d.SI[xlsxSI].R {
  162. value += v.T
  163. }
  164. return value, nil
  165. }
  166. return f.formattedValue(xlsx.S, d.SI[xlsxSI].T), nil
  167. case "str":
  168. return f.formattedValue(xlsx.S, xlsx.V), nil
  169. default:
  170. return f.formattedValue(xlsx.S, xlsx.V), nil
  171. }
  172. }
  173. // SetRowVisible provides a function to set visible of a single row by given
  174. // worksheet index and row index. For example, hide row 3 in Sheet1:
  175. //
  176. // xlsx.SetRowVisible("Sheet1", 2, false)
  177. //
  178. func (f *File) SetRowVisible(sheet string, rowIndex int, visible bool) {
  179. xlsx := f.workSheetReader(sheet)
  180. rows := rowIndex + 1
  181. cells := 0
  182. completeRow(xlsx, rows, cells)
  183. if visible {
  184. xlsx.SheetData.Row[rowIndex].Hidden = false
  185. return
  186. }
  187. xlsx.SheetData.Row[rowIndex].Hidden = true
  188. }
  189. // GetRowVisible provides a function to get visible of a single row by given
  190. // worksheet index and row index. For example, get visible state of row 3 in
  191. // Sheet1:
  192. //
  193. // xlsx.GetRowVisible("Sheet1", 2)
  194. //
  195. func (f *File) GetRowVisible(sheet string, rowIndex int) bool {
  196. xlsx := f.workSheetReader(sheet)
  197. rows := rowIndex + 1
  198. cells := 0
  199. completeRow(xlsx, rows, cells)
  200. return !xlsx.SheetData.Row[rowIndex].Hidden
  201. }