Explorar el Código

1. fixed get not get last column problem
2. correct bug of lettersToNumeric for mapping 'AAA1'

Daniel YC Lin hace 12 años
padre
commit
e2a5a0cf54
Se han modificado 2 ficheros con 17 adiciones y 115 borrados
  1. 8 49
      lib.go
  2. 9 66
      lib_test.go

+ 8 - 49
lib.go

@@ -6,7 +6,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"math"
 	"strconv"
 	"strings"
 )
@@ -131,60 +130,19 @@ func getRangeFromString(rangeString string) (lower int, upper int, error error)
 	return lower, upper, error
 }
 
-// positionalLetterMultiplier gives an integer multiplier to use for a
-// position in a letter based column identifer. For example, the
-// column ID "AA" is equivalent to 26*1 + 1, "BA" is equivalent to
-// 26*2 + 1 and "ABA" is equivalent to (676 * 1)+(26 * 2)+1 or
-// ((26**2)*1)+((26**1)*2)+((26**0))*1
-func positionalLetterMultiplier(extent, pos int) int {
-	var result float64
-	var power float64
-	var offset int
-	offset = pos + 1
-	power = float64(extent - offset)
-	result = math.Pow(26, power)
-	return int(result)
-}
-
 // lettersToNumeric is used to convert a character based column
 // reference to a zero based numeric column identifier.
 func lettersToNumeric(letters string) int {
-	var sum int = 0
-	var shift int
-	extent := len(letters)
-	for i, c := range letters {
-		// Just to make life akward.  If we think of this base
-		// 26 notation as being like HEX or binary we hit a
-		// nasty little problem.  The issue is that we have no
-		// 0s and therefore A can be both a 1 and a 0.  The
-		// value range of a letter is different in the most
-		// significant position if (and only if) there is more
-		// than one positions.  For example:
-		// "A" = 0
-		//               676 | 26 | 0
-		//               ----+----+----
-		//                 0 |  0 | 0
-		//
-		//  "Z" = 25
-		//                676 | 26 | 0
-		//                ----+----+----
-		//                  0 |  0 |  25
-		//   "AA" = 26
-		//                676 | 26 | 0
-		//                ----+----+----
-		//                  0 |  1 | 0     <--- note here - the value of "A" maps to both 1 and 0.
-		if i == 0 && extent > 1 {
-			shift = 1
-		} else {
-			shift = 0
-		}
-		multiplier := positionalLetterMultiplier(extent, i)
+	sum, mul, n := 0, 1, 0
+	for i := len(letters) - 1; i >= 0; i, mul, n = i-1, mul*26, 1 {
+		c := letters[i]
 		switch {
 		case 'A' <= c && c <= 'Z':
-			sum += multiplier * (int((c - 'A')) + shift)
+			n += int(c - 'A')
 		case 'a' <= c && c <= 'z':
-			sum += multiplier * (int((c - 'a')) + shift)
+			n += int(c - 'a')
 		}
+		sum += n * mul
 	}
 	return sum
 }
@@ -257,7 +215,7 @@ func makeRowFromRaw(rawrow xlsxRow) *Row {
 	var cell *Cell
 
 	row = new(Row)
-	upper = 0
+	upper = -1
 
 	for _, rawcell := range rawrow.C {
 		x, _, error := getCoordsFromCellIDString(rawcell.R)
@@ -268,6 +226,7 @@ func makeRowFromRaw(rawrow xlsxRow) *Row {
 			upper = x
 		}
 	}
+	upper++
 
 	row.Cells = make([]*Cell, upper)
 	for i := 0; i < upper; i++ {

+ 9 - 66
lib_test.go

@@ -83,72 +83,15 @@ func TestReadSharedStringsFromZipFile(t *testing.T) {
 }
 
 func TestLettersToNumeric(t *testing.T) {
-	var input string
-	var output int
-
-	input = "A"
-	output = lettersToNumeric(input)
-	if output != 0 {
-		t.Error("Expected output 'A' == 0, but got ", strconv.Itoa(output))
-	}
-	input = "z"
-	output = lettersToNumeric(input)
-	if output != 25 {
-		t.Error("Expected output 'z' == 25, but got ", strconv.Itoa(output))
-	}
-	input = "AA"
-	output = lettersToNumeric(input)
-	if output != 26 {
-		t.Error("Expected output 'AA' == 26, but got ", strconv.Itoa(output))
-	}
-	input = "Az"
-	output = lettersToNumeric(input)
-	if output != 51 {
-		t.Error("Expected output 'Az' == 51, but got ", strconv.Itoa(output))
-	}
-	input = "BA"
-	output = lettersToNumeric(input)
-	if output != 52 {
-		t.Error("Expected output 'BA' == 52, but got ", strconv.Itoa(output))
-	}
-	input = "Bz"
-	output = lettersToNumeric(input)
-	if output != 77 {
-		t.Error("Expected output 'Bz' == 77, but got ", strconv.Itoa(output))
-	}
-	input = "AAA"
-	output = lettersToNumeric(input)
-	if output != 676 {
-		t.Error("Expected output 'AAA' == 676, but got ", strconv.Itoa(output))
-	}
-
-}
-
-func TestPositionalLetterMultiplier(t *testing.T) {
-	var output int
-	output = positionalLetterMultiplier(1, 0)
-	if output != 1 {
-		t.Error("Expected positionalLetterMultiplier(1, 0) == 1, got ", output)
-	}
-	output = positionalLetterMultiplier(2, 0)
-	if output != 26 {
-		t.Error("Expected positionalLetterMultiplier(2, 0) == 26, got ", output)
-	}
-	output = positionalLetterMultiplier(2, 1)
-	if output != 1 {
-		t.Error("Expected positionalLetterMultiplier(2, 1) == 1, got ", output)
-	}
-	output = positionalLetterMultiplier(3, 0)
-	if output != 676 {
-		t.Error("Expected positionalLetterMultiplier(3, 0) == 676, got ", output)
-	}
-	output = positionalLetterMultiplier(3, 1)
-	if output != 26 {
-		t.Error("Expected positionalLetterMultiplier(3, 1) == 26, got ", output)
-	}
-	output = positionalLetterMultiplier(3, 2)
-	if output != 1 {
-		t.Error("Expected positionalLetterMultiplier(3, 2) == 1, got ", output)
+	cases := map[string]int{"A": 0, "G": 6, "z": 25, "AA": 26, "Az": 51,
+		"BA": 52, "Bz": 77, "ZA": 26*26 + 0, "ZZ": 26*26 + 25,
+		"AAA": 26*26 + 26 + 0, "AMI": 1022}
+	for input, ans := range cases {
+		output := lettersToNumeric(input)
+		if output != ans {
+			t.Error("Expected output '"+input+"' == ", ans,
+				"but got ", strconv.Itoa(output))
+		}
 	}
 }