|
@@ -17,6 +17,7 @@ import (
|
|
|
"log"
|
|
"log"
|
|
|
"strconv"
|
|
"strconv"
|
|
|
"strings"
|
|
"strings"
|
|
|
|
|
+ "unsafe"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
// ReadZipReader can be used to read an XLSX in memory without touching the
|
|
// ReadZipReader can be used to read an XLSX in memory without touching the
|
|
@@ -103,7 +104,7 @@ func JoinCellName(col string, row int) (string, error) {
|
|
|
if row < 1 {
|
|
if row < 1 {
|
|
|
return "", newInvalidRowNumberError(row)
|
|
return "", newInvalidRowNumberError(row)
|
|
|
}
|
|
}
|
|
|
- return fmt.Sprintf("%s%d", normCol, row), nil
|
|
|
|
|
|
|
+ return normCol + strconv.Itoa(row), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ColumnNameToNumber provides a function to convert Excel sheet column name
|
|
// ColumnNameToNumber provides a function to convert Excel sheet column name
|
|
@@ -190,6 +191,7 @@ func CoordinatesToCellName(col, row int) (string, error) {
|
|
|
}
|
|
}
|
|
|
colname, err := ColumnNumberToName(col)
|
|
colname, err := ColumnNumberToName(col)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
|
|
+ // Error should never happens here.
|
|
|
return "", fmt.Errorf("invalid cell coordinates [%d, %d]: %v", col, row, err)
|
|
return "", fmt.Errorf("invalid cell coordinates [%d, %d]: %v", col, row, err)
|
|
|
}
|
|
}
|
|
|
return fmt.Sprintf("%s%d", colname, row), nil
|
|
return fmt.Sprintf("%s%d", colname, row), nil
|
|
@@ -235,11 +237,47 @@ func namespaceStrictToTransitional(content []byte) []byte {
|
|
|
StrictNameSpaceSpreadSheet: NameSpaceSpreadSheet,
|
|
StrictNameSpaceSpreadSheet: NameSpaceSpreadSheet,
|
|
|
}
|
|
}
|
|
|
for s, n := range namespaceTranslationDic {
|
|
for s, n := range namespaceTranslationDic {
|
|
|
- content = bytes.Replace(content, []byte(s), []byte(n), -1)
|
|
|
|
|
|
|
+ content = bytesReplace(content, stringToBytes(s), stringToBytes(n), -1)
|
|
|
}
|
|
}
|
|
|
return content
|
|
return content
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// stringToBytes cast a string to bytes pointer and assign the value of this
|
|
|
|
|
+// pointer.
|
|
|
|
|
+func stringToBytes(s string) []byte {
|
|
|
|
|
+ return *(*[]byte)(unsafe.Pointer(&s))
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// bytesReplace replace old bytes with given new.
|
|
|
|
|
+func bytesReplace(s, old, new []byte, n int) []byte {
|
|
|
|
|
+ if n == 0 {
|
|
|
|
|
+ return s
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if len(old) < len(new) {
|
|
|
|
|
+ return bytes.Replace(s, old, new, n)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if n < 0 {
|
|
|
|
|
+ n = len(s)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ var wid, i, j, w int
|
|
|
|
|
+ for i, j = 0, 0; i < len(s) && j < n; j++ {
|
|
|
|
|
+ wid = bytes.Index(s[i:], old)
|
|
|
|
|
+ if wid < 0 {
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ w += copy(s[w:], s[i:i+wid])
|
|
|
|
|
+ w += copy(s[w:], new)
|
|
|
|
|
+ i += wid + len(old)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ w += copy(s[w:], s[i:])
|
|
|
|
|
+ return s[0:w]
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// genSheetPasswd provides a method to generate password for worksheet
|
|
// genSheetPasswd provides a method to generate password for worksheet
|
|
|
// protection by given plaintext. When an Excel sheet is being protected with
|
|
// protection by given plaintext. When an Excel sheet is being protected with
|
|
|
// a password, a 16-bit (two byte) long hash is generated. To verify a
|
|
// a password, a 16-bit (two byte) long hash is generated. To verify a
|