You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/filters/kspread/excel/sidewinder/cell.cpp

221 lines
4.3 KiB

/* Swinder - Portable library for spreadsheet
Copyright (C) 2003 Ariya Hidayat <ariya@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#include "cell.h"
#include "ustring.h"
#include "format.h"
#include "value.h"
#include <iostream>
namespace Swinder
{
class CellPrivate
{
public:
Sheet* sheet;
unsigned column;
unsigned row;
UString formula;
Value value;
Format* format;
int formatIndex;
unsigned columnSpan;
unsigned rowSpan;
static UString columnNames[256];
CellPrivate(Sheet* s, unsigned column, unsigned row);
~CellPrivate() { delete format; }
};
}
using namespace Swinder;
UString CellPrivate::columnNames[256];
CellPrivate::CellPrivate(Sheet* s, unsigned c, unsigned r):
sheet(s), column(c), row(r), format(0), formatIndex(-1), columnSpan(0), rowSpan(0)
{
}
Cell::Cell( Sheet* sheet, unsigned column, unsigned row )
{
d = new CellPrivate(sheet, column, row);
}
Cell::~Cell()
{
delete d;
}
Sheet* Cell::sheet()
{
return d->sheet;
}
unsigned Cell::column() const
{
return d->column;
}
unsigned Cell::row() const
{
return d->row;
}
UString Cell::name() const
{
return name( column(), row() );
}
UString Cell::name( unsigned column, unsigned row )
{
// column=0, row=0 is "A1"
return columnLabel( column ) + UString::number( row + 1 );
}
UString Cell::columnLabel() const
{
return columnLabel( column() );
}
UString Cell::columnLabel( unsigned column )
{
UString label;
// Excel has only up to 256 columns, so we cache those
if(column < 256 )
{
label = CellPrivate::columnNames[column];
// cache is not ready, so construct it first
if(label.isEmpty())
{
for(unsigned c = 0; c < 26; c++)
CellPrivate::columnNames[c] = UString(UChar((char)'A'+c));
for(unsigned d = 0; d < 256-26; d++)
{
char buf[3] = { (char)('A'+(d / 26)), (char)('A'+(d % 26)), 0};
CellPrivate::columnNames[d+26] = UString(buf);
}
label = CellPrivate::columnNames[column];
}
}
else
{
// otherwise, find with slower method
// how many characters for the column name?
unsigned digits = 1;
unsigned offset = 0;
for( unsigned limit = 26; column-offset >= limit; limit *= 26, digits++ )
offset += limit;
// extreme case e.g. column 4294967295 is "AATYHWUR" (8 characters)
if(digits < 9)
{
char ref[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
// from the last character
char* colp = ref + 9 - 1;
for( unsigned c = column - offset; digits; --digits, c/=26, colp-- )
*colp = char('A' + (c%26));
label = UString((const char*)(colp+1));
}
}
return label;
}
const Value& Cell::value() const
{
return d->value;
}
void Cell::setValue( const Value& value )
{
d->value = value;
}
const UString& Cell::formula() const
{
return d->formula;
}
void Cell::setFormula( const UString& formula )
{
d->formula = formula;
}
int Cell::formatIndex() const
{
return d->formatIndex;
}
void Cell::setFormatIndex( int index )
{
d->formatIndex = index;
}
Format Cell::format() const
{
if(!d->format)
d->format = new Format();
return Format(*d->format);
}
void Cell::setFormat( const Format& format )
{
if(!d->format)
d->format = new Format();
(*d->format) = format;
}
unsigned Cell::columnSpan() const
{
return d->columnSpan;
}
void Cell::setColumnSpan( unsigned span )
{
if( span < 1 ) return;
d->columnSpan = span;
}
unsigned Cell::rowSpan() const
{
return d->rowSpan;
}
void Cell::setRowSpan( unsigned span )
{
if( span < 1 ) return;
d->rowSpan = span;
}