Browse Source

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

Daniel YC Lin 12 years ago
parent
commit
720616c87c
2 changed files with 17 additions and 115 deletions
  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))
+		}
 	}
 }