https://bz.apache.org/ooo/show_bug.cgi?id=128623
[email protected] changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |ms_interoperability, | |regression --- Comment #1 from [email protected] --- The R1C1 to A1 format conversion needs to convert a 1-based decimal column number, to a 0-based base 26 (A-Z) column number. However it's not that simple, if we use "0" to represent an absent leading digit, then is it really base 26 when: 0A=0 0B=1 ... 0Z=25 AA=26 AB=27 ... AZ=52 BA=53 ... Only the right-most digit is base 26, the other digits are more like base 27, as 000A == 00A == 0A == A, so the "0" must be a 27th value... In ScColToAlpha() of main/sc/source/core/tool/address.cxx, we do this conversion using the following C++ code: ---snip--- void ScColToAlpha( rtl::OUStringBuffer& rBuf, SCCOL nCol ) { if (nCol < 26*26) { if (nCol < 26) rBuf.append( static_cast<sal_Unicode>( 'A' + static_cast<sal_uInt16>(nCol))); else { rBuf.append( static_cast<sal_Unicode>( 'A' + (static_cast<sal_uInt16>(nCol) / 26) - 1)); rBuf.append( static_cast<sal_Unicode>( 'A' + (static_cast<sal_uInt16>(nCol) % 26))); } } else { String aStr; while (nCol >= 26) { SCCOL nC = nCol % 26; aStr += static_cast<sal_Unicode>( 'A' + static_cast<sal_uInt16>(nC)); nCol = sal::static_int_cast<SCCOL>( nCol - nC ); nCol = nCol / 26 - 1; } aStr += static_cast<sal_Unicode>( 'A' + static_cast<sal_uInt16>(nCol)); aStr.Reverse(); rBuf.append( aStr); } } ---snip--- How does this work? The true part of the "if (nCol < 26*26)" is an optimization for smaller values, the "else" is the general algorithm for larger values: ---snip--- String aStr; while (nCol >= 26) { SCCOL nC = nCol % 26; aStr += static_cast<sal_Unicode>( 'A' + static_cast<sal_uInt16>(nC)); nCol = sal::static_int_cast<SCCOL>( nCol - nC ); nCol = nCol / 26 - 1; } aStr += static_cast<sal_Unicode>( 'A' + static_cast<sal_uInt16>(nCol)); aStr.Reverse(); ---snip--- That subtraction of 1 is confusing... Let's consider what happens for different values of nCol: 0 <= nCol < 26: - the while loop is skipped. - the result has 1 digit, 'A' + nCol, A=0, B=1, C=2, ..., Z=25. 26 <= nCol < 702 (27*26) - the while loop runs once - the result has 2 digits: - first digit is 'A' + floor((nCol / 26) - 1) - last digit is 'A' + (nCol % 26) 701 (27*26) <= nCol < 18278 (702*26) - the while loop runs twice - the result has 3 digits: - first digit is 'A' + (floor((floor(nCol / 26) - 1) / 26) - 1) - middle digit is 'A' + ((floor(nCol / 26) - 1) % 26) - last digit is 'A' + (nCol % 26) So: If (701 < nCol < 18728), the first digit will be 'A' + (floor((floor(nCol / 26) - 1) / 26) - 1). If (26 <= nCol), the next digit will be 'A' + ((floor(nCol / 26) - 1) % 26) The last digit will always be 'A' + (nCol % 26) Now how to translate this into the declarative format of XSLT? -- You are receiving this mail because: You are the assignee for the issue.
