mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-01-19 10:20:17 -06:00
exportcsv: allow to select more than 1 table at a time to export
This commit is contained in:
@@ -33,18 +33,26 @@ ExportCsvDialog::ExportCsvDialog(DBBrowserDB* db, QWidget* parent, const QString
|
||||
// Get list of tables to export
|
||||
objectMap objects = pdb->getBrowsableObjects();
|
||||
for(objectMap::ConstIterator i=objects.begin();i!=objects.end();++i)
|
||||
ui->comboTable->addItem(QIcon(QString(":icons/%1").arg(i.value().gettype())), i.value().getname());
|
||||
{
|
||||
ui->listTables->addItem(new QListWidgetItem(QIcon(QString(":icons/%1").arg(i.value().gettype())), i.value().getname()));
|
||||
}
|
||||
|
||||
// Sort list of tables and select the table specified in the selection parameter or alternatively the first one
|
||||
ui->comboTable->model()->sort(0);
|
||||
ui->listTables->model()->sort(0);
|
||||
if(selection.isEmpty())
|
||||
ui->comboTable->setCurrentIndex(0);
|
||||
{
|
||||
ui->listTables->setCurrentItem(ui->listTables->item(0));
|
||||
}
|
||||
else
|
||||
ui->comboTable->setCurrentIndex(ui->comboTable->findText(selection));
|
||||
{
|
||||
QList<QListWidgetItem*> items = ui->listTables->findItems(selection, Qt::MatchExactly);
|
||||
ui->listTables->setCurrentItem(items.at(0));
|
||||
}
|
||||
} else {
|
||||
// Hide table combo box
|
||||
ui->labelTable->setVisible(false);
|
||||
ui->comboTable->setVisible(false);
|
||||
ui->listTables->setVisible(false);
|
||||
resize(minimumSize());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,103 +61,169 @@ ExportCsvDialog::~ExportCsvDialog()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool ExportCsvDialog::exportQuery(const QString& sQuery, const QString& sFilename)
|
||||
{
|
||||
// Prepare the quote and separating characters
|
||||
QChar quoteChar = currentQuoteChar();
|
||||
QString quotequoteChar = QString(quoteChar) + quoteChar;
|
||||
QChar sepChar = currentSeparatorChar();
|
||||
QString newlineChar = "\r\n";
|
||||
|
||||
// Open file
|
||||
QFile file(sFilename);
|
||||
if(file.open(QIODevice::WriteOnly))
|
||||
{
|
||||
// Open text stream to the file
|
||||
QTextStream stream(&file);
|
||||
|
||||
QByteArray utf8Query = sQuery.toUtf8();
|
||||
sqlite3_stmt *stmt;
|
||||
|
||||
int status = sqlite3_prepare_v2(pdb->_db, utf8Query.data(), utf8Query.size(), &stmt, NULL);
|
||||
if(SQLITE_OK == status)
|
||||
{
|
||||
if(ui->checkHeader->isChecked())
|
||||
{
|
||||
int columns = sqlite3_column_count(stmt);
|
||||
for (int i = 0; i < columns; ++i)
|
||||
{
|
||||
QString content = QString::fromUtf8(sqlite3_column_name(stmt, i));
|
||||
if(content.contains(quoteChar) || content.contains(newlineChar))
|
||||
stream << quoteChar << content.replace(quoteChar, quotequoteChar) << quoteChar;
|
||||
else
|
||||
stream << content;
|
||||
if(i != columns - 1)
|
||||
stream << sepChar;
|
||||
}
|
||||
stream << newlineChar;
|
||||
}
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
int columns = sqlite3_column_count(stmt);
|
||||
size_t counter = 0;
|
||||
while(sqlite3_step(stmt) == SQLITE_ROW)
|
||||
{
|
||||
for (int i = 0; i < columns; ++i)
|
||||
{
|
||||
QString content = QString::fromUtf8(
|
||||
(const char*)sqlite3_column_blob(stmt, i),
|
||||
sqlite3_column_bytes(stmt, i));
|
||||
if(content.contains(quoteChar) || content.contains(sepChar) || content.contains('\n'))
|
||||
stream << quoteChar << content.replace(quoteChar, quotequoteChar) << quoteChar;
|
||||
else
|
||||
stream << content;
|
||||
if(i != columns - 1)
|
||||
stream << sepChar;
|
||||
}
|
||||
stream << newlineChar;
|
||||
if(counter % 1000 == 0)
|
||||
qApp->processEvents();
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
qApp->processEvents();
|
||||
|
||||
// Done writing the file
|
||||
file.close();
|
||||
} else {
|
||||
QMessageBox::warning(this, QApplication::applicationName(),
|
||||
tr("Could not open output file: %1").arg(sFilename));
|
||||
}
|
||||
}
|
||||
|
||||
void ExportCsvDialog::accept()
|
||||
{
|
||||
// Get filename
|
||||
QString fileName = QFileDialog::getSaveFileName(
|
||||
if(!m_sQuery.isEmpty())
|
||||
{
|
||||
// called from sqlexecute query tab
|
||||
QString sFilename = QFileDialog::getSaveFileName(
|
||||
this,
|
||||
tr("Choose a filename to export data"),
|
||||
PreferencesDialog::getSettingsValue("db", "defaultlocation").toString(),
|
||||
tr("Text files(*.csv *.txt)"));
|
||||
|
||||
// Only if the user hasn't clicked the cancel button
|
||||
if(fileName.size() > 0)
|
||||
{
|
||||
// save settings
|
||||
QSettings settings(QApplication::organizationName(), QApplication::organizationName());
|
||||
settings.beginGroup("exportcsv");
|
||||
settings.setValue("firstrowheader", ui->checkHeader->isChecked());
|
||||
settings.setValue("separator", currentSeparatorChar());
|
||||
settings.setValue("quotecharacter", currentQuoteChar());
|
||||
settings.endGroup();
|
||||
|
||||
// Create select statement when exporting an entire table
|
||||
if(m_sQuery.isEmpty())
|
||||
if(sFilename.isEmpty())
|
||||
{
|
||||
m_sQuery = QString("SELECT * from `%1`;").arg(ui->comboTable->currentText());
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare the quote and separating characters
|
||||
QChar quoteChar = currentQuoteChar();
|
||||
QString quotequoteChar = QString(quoteChar) + quoteChar;
|
||||
QChar sepChar = currentSeparatorChar();
|
||||
QString newlineChar = "\r\n";
|
||||
exportQuery(m_sQuery, sFilename);
|
||||
}
|
||||
else
|
||||
{
|
||||
// called from the File export menu
|
||||
QList<QListWidgetItem*> selectedItems = ui->listTables->selectedItems();
|
||||
|
||||
// Open file
|
||||
QFile file(fileName);
|
||||
if(file.open(QIODevice::WriteOnly))
|
||||
if(selectedItems.isEmpty())
|
||||
{
|
||||
// Open text stream to the file
|
||||
QTextStream stream(&file);
|
||||
QMessageBox::warning(this, QApplication::applicationName(),
|
||||
tr("Please select at least 1 table."));
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray utf8Query = m_sQuery.toUtf8();
|
||||
sqlite3_stmt *stmt;
|
||||
|
||||
int status = sqlite3_prepare_v2(pdb->_db, utf8Query.data(), utf8Query.size(), &stmt, NULL);
|
||||
if(SQLITE_OK == status)
|
||||
// Get filename
|
||||
QStringList filenames;
|
||||
if(selectedItems.size() == 1)
|
||||
{
|
||||
QString fileName = QFileDialog::getSaveFileName(
|
||||
this,
|
||||
tr("Choose a filename to export data"),
|
||||
PreferencesDialog::getSettingsValue("db", "defaultlocation").toString(),
|
||||
tr("Text files(*.csv *.txt)"));
|
||||
if(fileName.isEmpty())
|
||||
{
|
||||
if(ui->checkHeader->isChecked())
|
||||
{
|
||||
int columns = sqlite3_column_count(stmt);
|
||||
for (int i = 0; i < columns; ++i)
|
||||
{
|
||||
QString content = QString::fromUtf8(sqlite3_column_name(stmt, i));
|
||||
if(content.contains(quoteChar) || content.contains(newlineChar))
|
||||
stream << quoteChar << content.replace(quoteChar, quotequoteChar) << quoteChar;
|
||||
else
|
||||
stream << content;
|
||||
if(i != columns - 1)
|
||||
stream << sepChar;
|
||||
}
|
||||
stream << newlineChar;
|
||||
}
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
int columns = sqlite3_column_count(stmt);
|
||||
size_t counter = 0;
|
||||
while(sqlite3_step(stmt) == SQLITE_ROW)
|
||||
{
|
||||
for (int i = 0; i < columns; ++i)
|
||||
{
|
||||
QString content = QString::fromUtf8(
|
||||
(const char*)sqlite3_column_blob(stmt, i),
|
||||
sqlite3_column_bytes(stmt, i));
|
||||
if(content.contains(quoteChar) || content.contains(sepChar) || content.contains('\n'))
|
||||
stream << quoteChar << content.replace(quoteChar, quotequoteChar) << quoteChar;
|
||||
else
|
||||
stream << content;
|
||||
if(i != columns - 1)
|
||||
stream << sepChar;
|
||||
}
|
||||
stream << newlineChar;
|
||||
if(counter % 1000 == 0)
|
||||
qApp->processEvents();
|
||||
counter++;
|
||||
}
|
||||
close();
|
||||
return;
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
qApp->processEvents();
|
||||
filenames << fileName;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ask for folder
|
||||
QString csvfolder = QFileDialog::getExistingDirectory(
|
||||
this,
|
||||
tr("Choose a directory"),
|
||||
PreferencesDialog::getSettingsValue("db", "defaultlocation").toString(),
|
||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
|
||||
|
||||
// Done writing the file
|
||||
file.close();
|
||||
QMessageBox::information(this, QApplication::applicationName(), tr("Export completed."));
|
||||
QDialog::accept();
|
||||
} else {
|
||||
QMessageBox::warning(this, QApplication::applicationName(), tr("Could not open output file."));
|
||||
if(csvfolder.isEmpty())
|
||||
{
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
for(QList<QListWidgetItem*>::iterator it = selectedItems.begin(); it != selectedItems.end(); ++it)
|
||||
{
|
||||
filenames << QDir(csvfolder).filePath((*it)->text() + ".csv");
|
||||
}
|
||||
}
|
||||
|
||||
// Only if the user hasn't clicked the cancel button
|
||||
for(int i = 0; i < selectedItems.size(); ++i)
|
||||
{
|
||||
// if we are called from execute sql tab, query is already set
|
||||
// and we only export 1 select
|
||||
QString sQuery = QString("SELECT * from `%1`;").arg(selectedItems.at(i)->text());
|
||||
|
||||
exportQuery(sQuery, filenames.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
// save settings
|
||||
QSettings settings(QApplication::organizationName(), QApplication::organizationName());
|
||||
settings.beginGroup("exportcsv");
|
||||
settings.setValue("firstrowheader", ui->checkHeader->isChecked());
|
||||
settings.setValue("separator", currentSeparatorChar());
|
||||
settings.setValue("quotecharacter", currentQuoteChar());
|
||||
settings.endGroup();
|
||||
|
||||
|
||||
QMessageBox::information(this, QApplication::applicationName(), tr("Export completed."));
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void ExportCsvDialog::showCustomCharEdits()
|
||||
|
||||
@@ -22,16 +22,19 @@ private slots:
|
||||
void showCustomCharEdits();
|
||||
|
||||
private:
|
||||
Ui::ExportCsvDialog* ui;
|
||||
DBBrowserDB* pdb;
|
||||
|
||||
QString m_sQuery;
|
||||
|
||||
void setQuoteChar(const QChar& c);
|
||||
char currentQuoteChar() const;
|
||||
|
||||
void setSeparatorChar(const QChar& c);
|
||||
char currentSeparatorChar() const;
|
||||
|
||||
bool exportQuery(const QString& sQuery, const QString& sFilename);
|
||||
|
||||
private:
|
||||
Ui::ExportCsvDialog* ui;
|
||||
DBBrowserDB* pdb;
|
||||
|
||||
QString m_sQuery;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,28 +6,35 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>331</width>
|
||||
<height>145</height>
|
||||
<width>540</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Export data as CSV</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelTable">
|
||||
<property name="text">
|
||||
<string>&Table</string>
|
||||
<string>&Table(s)</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>comboTable</cstring>
|
||||
<cstring>listTables</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboTable"/>
|
||||
<widget class="QListWidget" name="listTables">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::MultiSelection</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelHeader">
|
||||
@@ -172,7 +179,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
@@ -185,13 +192,12 @@
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>comboTable</tabstop>
|
||||
<tabstop>listTables</tabstop>
|
||||
<tabstop>checkHeader</tabstop>
|
||||
<tabstop>comboFieldSeparator</tabstop>
|
||||
<tabstop>editCustomSeparator</tabstop>
|
||||
<tabstop>comboQuoteCharacter</tabstop>
|
||||
<tabstop>editCustomQuote</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
|
||||
@@ -1256,7 +1256,7 @@
|
||||
</action>
|
||||
<action name="fileExportCSVAction">
|
||||
<property name="text">
|
||||
<string>Table as CSV file...</string>
|
||||
<string>Table(s) as CSV file...</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Export a database table as a comma separated text file.</string>
|
||||
|
||||
Reference in New Issue
Block a user