diff --git a/app/src/main/java/org/gnucash/android/db/adapter/AccountsDbAdapter.java b/app/src/main/java/org/gnucash/android/db/adapter/AccountsDbAdapter.java index a6631ce3e..e19138306 100644 --- a/app/src/main/java/org/gnucash/android/db/adapter/AccountsDbAdapter.java +++ b/app/src/main/java/org/gnucash/android/db/adapter/AccountsDbAdapter.java @@ -206,7 +206,7 @@ public long bulkAddRecords(@NonNull List accountList, UpdateMethod upda stmt.bindString(3, account.getAccountType().name()); stmt.bindString(4, account.getCommodity().getCurrencyCode()); if (account.getColor() != Account.DEFAULT_COLOR) { - stmt.bindString(5, convertToRGBHexString(account.getColor())); + stmt.bindString(5, account.getColorHexString()); } stmt.bindLong(6, account.isFavorite() ? 1 : 0); stmt.bindString(7, account.getFullName()); @@ -230,10 +230,6 @@ public long bulkAddRecords(@NonNull List accountList, UpdateMethod upda return stmt; } - private String convertToRGBHexString(int color) { - return String.format("#%06X", (0xFFFFFF & color)); - } - /** * Marks all transactions for a given account as exported * @param accountUID Unique ID of the record to be marked as exported diff --git a/app/src/main/java/org/gnucash/android/export/ExportFormat.java b/app/src/main/java/org/gnucash/android/export/ExportFormat.java index 4e30654fa..7b6fc99c1 100644 --- a/app/src/main/java/org/gnucash/android/export/ExportFormat.java +++ b/app/src/main/java/org/gnucash/android/export/ExportFormat.java @@ -48,7 +48,6 @@ public String getExtension(){ case XML: return ".gnca"; case CSVA: - return ".csv"; case CSVT: return ".csv"; default: diff --git a/app/src/main/java/org/gnucash/android/export/csv/CsvAccountExporter.java b/app/src/main/java/org/gnucash/android/export/csv/CsvAccountExporter.java index a5c4842e6..47907c163 100644 --- a/app/src/main/java/org/gnucash/android/export/csv/CsvAccountExporter.java +++ b/app/src/main/java/org/gnucash/android/export/csv/CsvAccountExporter.java @@ -17,16 +17,17 @@ package org.gnucash.android.export.csv; import android.database.sqlite.SQLiteDatabase; + import com.crashlytics.android.Crashlytics; + +import org.gnucash.android.R; import org.gnucash.android.export.ExportParams; import org.gnucash.android.export.Exporter; import org.gnucash.android.model.Account; -import java.io.BufferedOutputStream; -import java.io.FileOutputStream; +import java.io.FileWriter; import java.io.IOException; -import java.io.OutputStreamWriter; -import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -61,84 +62,51 @@ public CsvAccountExporter(ExportParams params, SQLiteDatabase db) { @Override public List generateExport() throws ExporterException { - OutputStreamWriter writerStream = null; - CsvWriter writer = null; String outputFile = getExportCacheFilePath(); - try { - FileOutputStream fileOutputStream = new FileOutputStream(outputFile); - BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream); - writerStream = new OutputStreamWriter(bufferedOutputStream); - writer = new CsvWriter(writerStream); + try (CsvWriter writer = new CsvWriter(new FileWriter(outputFile), mCsvSeparator + "")) { generateExport(writer); } catch (IOException ex){ Crashlytics.log("Error exporting CSV"); Crashlytics.logException(ex); - } finally { - if (writerStream != null) { - try { - writerStream.close(); - } catch (IOException e) { - throw new ExporterException(mExportParams, e); - } - } + throw new ExporterException(mExportParams, ex); } - List exportedFiles = new ArrayList<>(); - exportedFiles.add(outputFile); - - return exportedFiles; + return Arrays.asList(outputFile); } - public void generateExport(final CsvWriter writer) throws ExporterException { + /** + * Writes out all the accounts in the system as CSV to the provided writer + * @param csvWriter Destination for the CSV export + * @throws ExporterException if an error occurred while writing to the stream + */ + public void generateExport(final CsvWriter csvWriter) throws ExporterException { try { - String separator = mCsvSeparator + ""; - List names = new ArrayList(); - names.add("type"); - names.add("full_name"); - names.add("name"); - names.add("code"); - names.add("description"); - names.add("color"); - names.add("notes"); - names.add("commoditym"); - names.add("commodityn"); - names.add("hidden"); - names.add("tax"); - names.add("place_holder"); - + List names = Arrays.asList(mContext.getResources().getStringArray(R.array.csv_account_headers)); List accounts = mAccountsDbAdapter.getAllRecords(); for(int i = 0; i < names.size(); i++) { - writer.write(names.get(i) + separator); + csvWriter.writeToken(names.get(i)); } - writer.write("\n"); - for(int i = 0; i < accounts.size(); i++) { - Account account = accounts.get(i); - - writer.write(account.getAccountType().toString() + separator); - writer.write(account.getFullName() + separator); - writer.write(account.getName() + separator); - - //Code - writer.write(separator); - - writer.write(account.getDescription() + separator); - writer.write(account.getColor() + separator); - - //Notes - writer.write(separator); - writer.write(account.getCommodity().getCurrencyCode() + separator); - writer.write("CURRENCY" + separator); - writer.write(account.isHidden()?"T":"F" + separator); + csvWriter.newLine(); + for (Account account : accounts) { + csvWriter.writeToken(account.getAccountType().toString()); + csvWriter.writeToken(account.getFullName()); + csvWriter.writeToken(account.getName()); - writer.write("F" + separator); + csvWriter.writeToken(null); //Account code + csvWriter.writeToken(account.getDescription()); + csvWriter.writeToken(account.getColorHexString()); + csvWriter.writeToken(null); //Account notes - writer.write(account.isPlaceholderAccount()?"T":"F" + separator); + csvWriter.writeToken(account.getCommodity().getCurrencyCode()); + csvWriter.writeToken("CURRENCY"); + csvWriter.writeToken(account.isHidden() ? "T" : "F"); - writer.write("\n"); + csvWriter.writeToken("F"); //Tax + csvWriter.writeEndToken(account.isPlaceholderAccount() ? "T": "F"); } - } catch (Exception e) { + } catch (IOException e) { Crashlytics.logException(e); throw new ExporterException(mExportParams, e); } diff --git a/app/src/main/java/org/gnucash/android/export/csv/CsvTransactionsExporter.java b/app/src/main/java/org/gnucash/android/export/csv/CsvTransactionsExporter.java index c0419f7c7..56f9a0766 100644 --- a/app/src/main/java/org/gnucash/android/export/csv/CsvTransactionsExporter.java +++ b/app/src/main/java/org/gnucash/android/export/csv/CsvTransactionsExporter.java @@ -34,7 +34,6 @@ import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; @@ -82,12 +81,10 @@ public List generateExport() throws ExporterException { } catch (IOException ex){ Crashlytics.log("Error exporting CSV"); Crashlytics.logException(ex); + throw new ExporterException(mExportParams, ex); } - List exportedFiles = new ArrayList<>(); - exportedFiles.add(outputFile); - - return exportedFiles; + return Arrays.asList(outputFile); } /** diff --git a/app/src/main/java/org/gnucash/android/model/Account.java b/app/src/main/java/org/gnucash/android/model/Account.java index 4fa09fecb..f6234d304 100644 --- a/app/src/main/java/org/gnucash/android/model/Account.java +++ b/app/src/main/java/org/gnucash/android/model/Account.java @@ -282,6 +282,14 @@ public int getColor() { return mColor; } + /** + * Returns the account color as an RGB hex string + * @return Hex color of the account + */ + public String getColorHexString(){ + return String.format("#%06X", (0xFFFFFF & mColor)); + } + /** * Sets the color of the account. * @param color Color as an int as returned by {@link Color}. diff --git a/app/src/main/java/org/gnucash/android/ui/settings/AccountPreferencesFragment.java b/app/src/main/java/org/gnucash/android/ui/settings/AccountPreferencesFragment.java index 7a35d542c..977b06b57 100644 --- a/app/src/main/java/org/gnucash/android/ui/settings/AccountPreferencesFragment.java +++ b/app/src/main/java/org/gnucash/android/ui/settings/AccountPreferencesFragment.java @@ -27,17 +27,26 @@ import android.support.v7.preference.ListPreference; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceFragmentCompat; +import android.widget.Toast; + +import com.crashlytics.android.Crashlytics; import org.gnucash.android.R; import org.gnucash.android.app.GnuCashApplication; import org.gnucash.android.db.DatabaseSchema; +import org.gnucash.android.db.adapter.BooksDbAdapter; import org.gnucash.android.db.adapter.CommoditiesDbAdapter; +import org.gnucash.android.export.ExportAsyncTask; +import org.gnucash.android.export.ExportFormat; +import org.gnucash.android.export.ExportParams; +import org.gnucash.android.export.Exporter; import org.gnucash.android.model.Money; import org.gnucash.android.ui.account.AccountsActivity; import org.gnucash.android.ui.settings.dialog.DeleteAllAccountsConfirmationDialog; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ExecutionException; /** * Account settings fragment inside the Settings activity @@ -48,6 +57,8 @@ public class AccountPreferencesFragment extends PreferenceFragmentCompat implements Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener{ + private static final int REQUEST_EXPORT_FILE = 0xC5; + List mCurrencyEntries = new ArrayList<>(); List mCurrencyEntryValues = new ArrayList<>(); @@ -91,6 +102,9 @@ public void onResume() { Preference preference = findPreference(getString(R.string.key_import_accounts)); preference.setOnPreferenceClickListener(this); + preference = findPreference(getString(R.string.key_export_accounts_csv)); + preference.setOnPreferenceClickListener(this); + preference = findPreference(getString(R.string.key_delete_all_accounts)); preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override @@ -137,9 +151,29 @@ public boolean onPreferenceClick(Preference preference) { return true; } + if (key.equals(getString(R.string.key_export_accounts_csv))){ + selectExportFile(); + return true; + } + return false; } + /** + * Open a chooser for user to pick a file to export to + */ + private void selectExportFile() { + Intent createIntent = new Intent(Intent.ACTION_CREATE_DOCUMENT); + createIntent.setType("*/*").addCategory(Intent.CATEGORY_OPENABLE); + String bookName = BooksDbAdapter.getInstance().getActiveBookDisplayName(); + + String filename = Exporter.buildExportFilename(ExportFormat.CSVA, bookName); + createIntent.setType("application/text"); + + createIntent.putExtra(Intent.EXTRA_TITLE, filename); + startActivityForResult(createIntent, REQUEST_EXPORT_FILE); + } + @Override public boolean onPreferenceChange(Preference preference, Object newValue) { if (preference.getKey().equals(getString(R.string.key_default_currency))){ @@ -167,6 +201,22 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { AccountsActivity.importXmlFileFromIntent(getActivity(), data, null); } break; + + case REQUEST_EXPORT_FILE: + if (resultCode == Activity.RESULT_OK && data != null){ + ExportParams exportParams = new ExportParams(ExportFormat.CSVA); + exportParams.setExportTarget(ExportParams.ExportTarget.URI); + exportParams.setExportLocation(data.getData().toString()); + ExportAsyncTask exportTask = new ExportAsyncTask(getActivity(), GnuCashApplication.getActiveDb()); + + try { + exportTask.execute(exportParams).get(); + } catch (InterruptedException | ExecutionException e) { + Crashlytics.logException(e); + Toast.makeText(getActivity(), "An error occurred during the Accounts CSV export", + Toast.LENGTH_LONG).show(); + } + } } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4c159f49c..2644d560e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -126,7 +126,7 @@ Enter an amount to save the transaction An error occurred while importing the GnuCash accounts GnuCash Accounts successfully imported - Import account structure exported from GnuCash desktop + Import account structure from GnuCash XML Import GnuCash XML Delete all accounts in the database. All transactions will be deleted as well. @@ -463,6 +463,9 @@ Export to \'/Apps/GnuCash Android/\' folder on Dropbox Preferences Yes, I\'m sure + export_accounts_csv_key + Export all accounts (without transactions) to CSV + Export as CSV Date Transaction ID @@ -481,4 +484,18 @@ Reconcile Date Rate/Price + + Type + Full Name + Name + Code + Description + Color + Notes + Commoditym + Commodityn + Hidden + Tax + Placeholder + diff --git a/app/src/main/res/xml/fragment_account_preferences.xml b/app/src/main/res/xml/fragment_account_preferences.xml index ace62559e..d8299897d 100644 --- a/app/src/main/res/xml/fragment_account_preferences.xml +++ b/app/src/main/res/xml/fragment_account_preferences.xml @@ -28,6 +28,9 @@ +