filters
csvexport.cc00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <csvexport.h>
00022
00023 #include <qfile.h>
00024 #include <qtextcodec.h>
00025
00026 #include <kdebug.h>
00027 #include <kmessagebox.h>
00028 #include <kgenericfactory.h>
00029 #include <KoFilterChain.h>
00030 #include <KoFilterManager.h>
00031
00032 #include <kspread_map.h>
00033 #include <kspread_sheet.h>
00034 #include <kspread_doc.h>
00035 #include <kspread_view.h>
00036 #include <selection.h>
00037
00038 #include <csvexportdialog.h>
00039
00040 using namespace KSpread;
00041
00042 typedef KGenericFactory<CSVExport, KoFilter> CSVExportFactory;
00043 K_EXPORT_COMPONENT_FACTORY( libcsvexport, CSVExportFactory( "kofficefilters" ) )
00044
00045 class Cell
00046 {
00047 public:
00048 int row, col;
00049 QString text;
00050
00051 bool operator < ( const Cell & c ) const
00052 {
00053 return row < c.row || ( row == c.row && col < c.col );
00054 }
00055 bool operator == ( const Cell & c ) const
00056 {
00057 return row == c.row && col == c.col;
00058 }
00059 };
00060
00061
00062 CSVExport::CSVExport( KoFilter *, const char *, const QStringList & )
00063 : KoFilter(), m_eol("\n")
00064 {
00065 }
00066
00067 QString CSVExport::exportCSVCell( Sheet const * const sheet, int col, int row, QChar const & textQuote, QChar csvDelimiter )
00068 {
00069
00070
00071
00072
00073
00074
00075 KSpread::Cell const * const cell = sheet->cellAt( col, row );
00076 QString text;
00077
00078 if ( !cell->isDefault() && !cell->isEmpty() )
00079 {
00080 if ( cell->isFormula() )
00081 text = cell->strOutText();
00082 else if ( !cell->link().isEmpty() )
00083 text = cell->text();
00084 else if( cell->isTime() )
00085 text = cell->value().asTime().toString("hh:mm:ss");
00086 else if( cell->isDate() )
00087 text = cell->value().asDate().toString("yyyy-MM-dd");
00088 else
00089 text = cell->strOutText();
00090 }
00091
00092
00093 bool quote = false;
00094 if ( !text.isEmpty() )
00095 {
00096 if ( text.find( textQuote ) != -1 )
00097 {
00098 QString doubleTextQuote(textQuote);
00099 doubleTextQuote.append(textQuote);
00100 text.replace(textQuote, doubleTextQuote);
00101 quote = true;
00102
00103 } else if ( text[0].isSpace() || text[text.length()-1].isSpace() )
00104 quote = true;
00105 else if ( text.find( csvDelimiter ) != -1 )
00106 quote = true;
00107 else if ( text.find( "\n" ) != -1 || text.find( "\r" ) != -1 )
00108 quote = true;
00109 }
00110
00111 if ( quote ) {
00112 text.prepend(textQuote);
00113 text.append(textQuote);
00114 }
00115
00116 return text;
00117 }
00118
00119
00120
00121 KoFilter::ConversionStatus CSVExport::convert( const QCString & from, const QCString & to )
00122 {
00123 kdDebug(30501) << "CSVExport::convert" << endl;
00124 KoDocument* document = m_chain->inputDocument();
00125
00126 if ( !document )
00127 return KoFilter::StupidError;
00128
00129 if ( !::qt_cast<const KSpread::Doc *>( document ) )
00130 {
00131 kdWarning(30501) << "document isn't a KSpread::Doc but a " << document->className() << endl;
00132 return KoFilter::NotImplemented;
00133 }
00134 if ( ( to != "text/x-csv" && to != "text/plain" ) || from != "application/x-kspread" )
00135 {
00136 kdWarning(30501) << "Invalid mimetypes " << to << " " << from << endl;
00137 return KoFilter::NotImplemented;
00138 }
00139
00140 Doc const * const ksdoc = static_cast<const Doc *>(document);
00141
00142 if ( ksdoc->mimeType() != "application/x-kspread" )
00143 {
00144 kdWarning(30501) << "Invalid document mimetype " << ksdoc->mimeType() << endl;
00145 return KoFilter::NotImplemented;
00146 }
00147
00148 CSVExportDialog *expDialog = 0;
00149 if (!m_chain->manager()->getBatchMode())
00150 {
00151 expDialog= new CSVExportDialog( 0 );
00152
00153 if (!expDialog)
00154 {
00155 kdError(30501) << "Dialog has not been created! Aborting!" << endl;
00156 return KoFilter::StupidError;
00157 }
00158 expDialog->fillSheet( ksdoc->map() );
00159
00160 if ( !expDialog->exec() )
00161 {
00162 delete expDialog;
00163 return KoFilter::UserCancelled;
00164 }
00165 }
00166
00167 QTextCodec* codec = 0;
00168 QChar csvDelimiter;
00169 if (expDialog)
00170 {
00171 codec = expDialog->getCodec();
00172 if ( !codec )
00173 {
00174 delete expDialog;
00175 return KoFilter::StupidError;
00176 }
00177 csvDelimiter = expDialog->getDelimiter();
00178 m_eol = expDialog->getEndOfLine();
00179 }
00180 else
00181 {
00182 codec = QTextCodec::codecForName("UTF-8");
00183 csvDelimiter = ',';
00184 }
00185
00186
00187
00188
00189
00190
00191
00192 bool first = true;
00193 QString str;
00194 QChar textQuote;
00195 if (expDialog)
00196 textQuote = expDialog->getTextQuote();
00197 else
00198 textQuote = '"';
00199
00200 if ( expDialog && expDialog->exportSelectionOnly() )
00201 {
00202 kdDebug(30501) << "Export as selection mode" << endl;
00203 View const * const view = static_cast<View*>(ksdoc->views().getFirst());
00204
00205 if ( !view )
00206 {
00207 delete expDialog;
00208 return KoFilter::StupidError;
00209 }
00210
00211 Sheet const * const sheet = view->activeSheet();
00212
00213 QRect selection = view->selectionInfo()->lastRange();
00214
00215
00216
00217 int right = selection.right();
00218 int bottom = selection.bottom();
00219 int CSVMaxRow = 0;
00220 int CSVMaxCol = 0;
00221
00222 for ( int idxRow = 1, row = selection.top(); row <= bottom; ++row, ++idxRow )
00223 {
00224 for ( int idxCol = 1, col = selection.left(); col <= right; ++col, ++idxCol )
00225 {
00226 if( ! sheet->cellAt( col, row )->isEmpty() )
00227 {
00228 if ( idxRow > CSVMaxRow )
00229 CSVMaxRow = idxRow;
00230
00231 if ( idxCol > CSVMaxCol )
00232 CSVMaxCol = idxCol;
00233 }
00234 }
00235 }
00236
00237 for ( int idxRow = 1, row = selection.top();
00238 row <= bottom && idxRow <= CSVMaxRow; ++row, ++idxRow )
00239 {
00240 int idxCol = 1;
00241 for ( int col = selection.left();
00242 col <= right && idxCol <= CSVMaxCol; ++col, ++idxCol )
00243 {
00244 str += exportCSVCell( sheet, col, row, textQuote, csvDelimiter );
00245
00246 if ( idxCol < CSVMaxCol )
00247 str += csvDelimiter;
00248 }
00249
00250
00251 for ( ; idxCol < CSVMaxCol; ++idxCol )
00252 str += csvDelimiter;
00253
00254 str += m_eol;
00255 }
00256 }
00257 else
00258 {
00259 kdDebug(30501) << "Export as full mode" << endl;
00260 QPtrListIterator<Sheet> it( ksdoc->map()->sheetList() );
00261 for( ; it.current(); ++it )
00262 {
00263 Sheet const * const sheet = it.current();
00264
00265 if (expDialog && !expDialog->exportSheet( sheet->sheetName() ) )
00266 {
00267 continue;
00268 }
00269
00270
00271
00272
00273 int sheetMaxRow = sheet->maxRow();
00274 int sheetMaxCol = sheet->maxColumn();
00275 int CSVMaxRow = 0;
00276 int CSVMaxCol = 0;
00277
00278 for ( int row = 1 ; row <= sheetMaxRow ; ++row)
00279 {
00280 for ( int col = 1 ; col <= sheetMaxCol ; col++ )
00281 {
00282 if( ! sheet->cellAt( col, row )->isEmpty() )
00283 {
00284 if ( row > CSVMaxRow )
00285 CSVMaxRow = row;
00286
00287 if ( col > CSVMaxCol )
00288 CSVMaxCol = col;
00289 }
00290 }
00291 }
00292
00293
00294 if ( CSVMaxRow + CSVMaxCol == 0)
00295 continue;
00296
00297 kdDebug(30501) << "Max row x column: " << CSVMaxRow << " x " << CSVMaxCol << endl;
00298
00299
00300 if ( !first || ( expDialog && expDialog->printAlwaysSheetDelimiter() ) )
00301 {
00302 if ( !first)
00303 str += m_eol;
00304
00305 QString name;
00306 if (expDialog)
00307 name = expDialog->getSheetDelimiter();
00308 else
00309 name = "********<SHEETNAME>********";
00310 const QString tname( i18n("<SHEETNAME>") );
00311 int pos = name.find( tname );
00312 if ( pos != -1 )
00313 {
00314 name.replace( pos, tname.length(), sheet->sheetName() );
00315 }
00316 str += name;
00317 str += m_eol;
00318 str += m_eol;
00319 }
00320
00321 first = false;
00322
00323
00324
00325
00326 int value = 0;
00327 int step = CSVMaxRow > 50 ? CSVMaxRow/50 : 1;
00328
00329
00330 for ( int row = 1, i = 1 ; row <= CSVMaxRow ; ++row, ++i )
00331 {
00332 if ( i > step )
00333 {
00334 value += 2;
00335 emit sigProgress(value);
00336 i = 0;
00337 }
00338
00339 QString collect;
00340
00341 for ( int col = 1 ; col <= CSVMaxCol ; col++ )
00342 {
00343 const QString txt = exportCSVCell( sheet, col, row, textQuote, csvDelimiter );
00344
00345
00346 if (!txt.isEmpty()) {
00347 str += collect + txt;
00348 collect = QString();
00349 }
00350
00351 collect += csvDelimiter;
00352 }
00353
00354
00355
00356 str += m_eol;
00357 }
00358 }
00359 }
00360
00361 emit sigProgress(100);
00362
00363 QFile out(m_chain->outputFile());
00364 if ( !out.open( IO_WriteOnly ) )
00365 {
00366 kdError(30501) << "Unable to open output file!" << endl;
00367 out.close();
00368 delete expDialog;
00369 return KoFilter::StupidError;
00370 }
00371
00372 QTextStream outStream( &out );
00373 outStream.setCodec( codec );
00374
00375 outStream << str;
00376
00377 out.close();
00378 delete expDialog;
00379 return KoFilter::OK;
00380 }
00381
00382 #include <csvexport.moc>
|