Merge lp:~tlnd/financisto/csv-export into lp:~financisto-dev/financisto/trunk

Proposed by tlnd
Status: Merged
Approved by: Denis Solonenko
Approved revision: 60
Merged at revision: 82
Proposed branch: lp:~tlnd/financisto/csv-export
Merge into: lp:~financisto-dev/financisto/trunk
Diff against target: 344 lines (+136/-40)
8 files modified
assets/credits.htm (+1/-1)
res/layout/csv_export.xml (+38/-25)
res/values-de/strings.xml (+5/-3)
res/values/common.xml (+5/-0)
res/values/strings.xml (+2/-0)
src/ru/orangesoftware/financisto/activity/CsvExportActivity.java (+55/-2)
src/ru/orangesoftware/financisto/activity/MainActivity.java (+12/-5)
src/ru/orangesoftware/financisto/export/CSVExport.java (+18/-4)
To merge this branch: bzr merge lp:~tlnd/financisto/csv-export
Reviewer Review Type Date Requested Status
Denis Solonenko Approve
Review via email: mp+35904@code.launchpad.net

Commit message

CSV export: Custom value separator and persistent preferences

Description of the change

Hey,

I tackled the blueprint to "Allow custom separator for values in CSV export". Besides the comma, the user now can also select a semicolon or a tabulator. Additionally, he can choose whether the headers should be exported. Furthermore, the selection is persistent, thus the user does not have to reselect his preferences every time he does an export.

It would be great if somebody could review the code. If necessary, I'm willing to rework it to get it merged eventually.

Regards,
Timo

To post a comment you must log in.
Revision history for this message
Denis Solonenko (denis-solonenko) wrote :

Looks good, thank you! Please integrate into trunk.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'assets/credits.htm'
2--- assets/credits.htm 2010-09-04 22:15:18 +0000
3+++ assets/credits.htm 2010-09-18 00:44:43 +0000
4@@ -31,7 +31,7 @@
5 </p>
6 <p><b>Contributors</b></p>
7 <p>
8-tlnd<br/>
9+Timo Lindhorst<br/>
10 </p>
11 <p><b>Localizators</b></p>
12 <p>
13
14=== modified file 'res/layout/csv_export.xml'
15--- res/layout/csv_export.xml 2010-06-02 15:22:10 +0000
16+++ res/layout/csv_export.xml 2010-09-18 00:44:43 +0000
17@@ -19,33 +19,46 @@
18 android:text="@string/period"></TextView>
19 <Button android:layout_height="wrap_content" android:id="@+id/bPeriod"
20 android:layout_width="fill_parent"></Button>
21+ <View android:layout_height="1dp" android:background="@drawable/divider_horizontal_dark"
22+ android:layout_width="fill_parent" android:layout_marginLeft="10dp"
23+ android:layout_marginRight="10dp" />
24+
25 <TableLayout android:layout_height="wrap_content"
26- android:layout_width="fill_parent">
27- <TableRow android:layout_width="wrap_content"
28- android:layout_height="wrap_content">
29- <TextView android:layout_height="wrap_content"
30- android:layout_width="fill_parent" android:layout_marginLeft="3dp"
31- android:text="@string/decimals" android:layout_weight="1"></TextView>
32- <TextView android:layout_height="wrap_content"
33- android:layout_width="fill_parent" android:layout_marginLeft="3dp"
34- android:layout_weight="1" android:text="@string/decimal_separator"></TextView>
35- <TextView android:layout_height="wrap_content"
36- android:layout_width="fill_parent" android:layout_marginLeft="3dp"
37- android:layout_weight="1" android:text="@string/group_separator"></TextView>
38- </TableRow>
39- <TableRow android:layout_width="wrap_content"
40- android:layout_height="wrap_content">
41- <Spinner android:layout_height="wrap_content" android:id="@+id/spinnerDecimals"
42- android:entries="@array/decimals" android:layout_width="wrap_content"
43- android:layout_weight="1"></Spinner>
44- <Spinner android:layout_height="wrap_content"
45- android:layout_width="wrap_content" android:layout_weight="1"
46- android:id="@+id/spinnerDecimalSeparators" android:entries="@array/decimal_separators"></Spinner>
47- <Spinner android:layout_height="wrap_content"
48- android:layout_width="wrap_content" android:layout_weight="1"
49- android:id="@+id/spinnerGroupSeparators" android:entries="@array/group_separators"></Spinner>
50+ android:layout_width="fill_parent"
51+ android:stretchColumns="*">
52+ <TableRow>
53+ <TextView android:layout_marginLeft="3dp"
54+ android:text="@string/decimals"></TextView>
55+ <TextView android:layout_marginLeft="3dp"
56+ android:text="@string/decimal_separator"></TextView>
57+ <TextView android:layout_marginLeft="3dp"
58+ android:text="@string/group_separator"></TextView>
59+ </TableRow>
60+ <TableRow>
61+ <Spinner android:id="@+id/spinnerDecimals"
62+ android:entries="@array/decimals"></Spinner>
63+ <Spinner android:id="@+id/spinnerDecimalSeparators"
64+ android:entries="@array/decimal_separators"></Spinner>
65+ <Spinner android:id="@+id/spinnerGroupSeparators"
66+ android:entries="@array/group_separators"></Spinner>
67+ </TableRow>
68+ <View android:layout_height="1dp" android:background="@drawable/divider_horizontal_dark"
69+ android:layout_width="fill_parent" android:layout_marginLeft="10dp"
70+ android:layout_marginRight="10dp" />
71+ <TableRow>
72+ <TextView android:layout_marginLeft="3dp"
73+ android:text="@string/field_separator"></TextView>
74+ <TextView android:layout_marginLeft="3dp"
75+ android:text="@string/include_header"></TextView>
76+ </TableRow>
77+ <TableRow>
78+ <Spinner android:id="@+id/spinnerFieldSeparator"
79+ android:entries="@array/field_separators"></Spinner>
80+ <CheckBox android:id="@+id/checkboxIncludeHeader"
81+ android:checked="true"></CheckBox>
82 </TableRow>
83 </TableLayout>
84+
85 <include layout="@layout/ok_cancel_buttons" />
86
87-</LinearLayout>
88+</LinearLayout>
89\ No newline at end of file
90
91=== modified file 'res/values-de/strings.xml'
92--- res/values-de/strings.xml 2010-08-24 11:39:10 +0000
93+++ res/values-de/strings.xml 2010-09-18 00:44:43 +0000
94@@ -177,9 +177,11 @@
95 <string name="is_default">Standard</string>
96 <string name="is_included_into_totals">Bei Gesamtrechnung berücksichtigen</string>
97 <string name="is_included_into_totals_summary">Berücksichtigt die Transaktionen dieses Kontos in der Gesamtrechnung</string>
98- <string name="decimals">\nDezimal</string>
99- <string name="decimal_separator">Dezimal\ntrenner</string>
100- <string name="group_separator">Gruppen\nstrenner</string>
101+ <string name="decimals">Dezimal-\nstellen</string>
102+ <string name="decimal_separator">Dezimal-\ntrenner</string>
103+ <string name="group_separator">Gruppen-\ntrenner</string>
104+ <string name="field_separator">Feld-\ntrenner</string>
105+ <string name="include_header">Spalten-\nüberschriften</string>
106 <string name="delete_account_confirm">Konto löschen?</string>
107 <string name="delete_transaction_confirm">Transaktion löschen?</string>
108 <string name="delete_budget_confirm">Budget löschen?</string>
109
110=== modified file 'res/values/common.xml'
111--- res/values/common.xml 2010-09-12 11:06:23 +0000
112+++ res/values/common.xml 2010-09-18 00:44:43 +0000
113@@ -56,6 +56,11 @@
114 <item>\' \'</item>
115 <item>\'\'</item>
116 </string-array>
117+ <string-array name="field_separators">
118+ <item>\',\'</item>
119+ <item>\';\'</item>
120+ <item>\'\t\'</item>
121+ </string-array>
122 <string-array name="sort_order_entities">
123 <item>1</item>
124 <item>2</item>
125
126=== modified file 'res/values/strings.xml'
127--- res/values/strings.xml 2010-09-12 11:06:23 +0000
128+++ res/values/strings.xml 2010-09-18 00:44:43 +0000
129@@ -209,6 +209,8 @@
130 <string name="decimals">\nDecimals</string>
131 <string name="decimal_separator">Decimal\nseparator</string>
132 <string name="group_separator">Group\nseparator</string>
133+ <string name="field_separator">Field\nseparator</string>
134+ <string name="include_header">Include\nheader</string>
135 <string name="delete_account_confirm">Delete account?</string>
136 <string name="delete_transaction_confirm">Delete transaction?</string>
137 <string name="delete_budget_confirm">Delete budget?</string>
138
139=== modified file 'src/ru/orangesoftware/financisto/activity/CsvExportActivity.java'
140--- src/ru/orangesoftware/financisto/activity/CsvExportActivity.java 2010-06-06 08:16:58 +0000
141+++ src/ru/orangesoftware/financisto/activity/CsvExportActivity.java 2010-09-18 00:44:43 +0000
142@@ -21,10 +21,12 @@
143 import ru.orangesoftware.financisto.utils.DateUtils.PeriodType;
144 import android.app.Activity;
145 import android.content.Intent;
146+import android.content.SharedPreferences;
147 import android.os.Bundle;
148 import android.view.View;
149 import android.view.View.OnClickListener;
150 import android.widget.Button;
151+import android.widget.CheckBox;
152 import android.widget.Spinner;
153
154 public class CsvExportActivity extends Activity {
155@@ -34,6 +36,8 @@
156 public static final String CSV_EXPORT_GROUP_SEPARATOR = "CSV_EXPORT_GROUP_SEPARATOR";
157 public static final String CSV_EXPORT_DATE_FORMAT = "CSV_EXPORT_DATE_FORMAT";
158 public static final String CSV_EXPORT_TIME_FORMAT = "CSV_EXPORT_TIME_FORMAT";
159+ public static final String CSV_EXPORT_FIELD_SEPARATOR = "CSV_EXPORT_FIELD_SEPARATOR";
160+ public static final String CSV_EXPORT_INCLUDE_HEADER = "CSV_EXPORT_INCLUDE_HEADER";
161
162 private final WhereFilter filter = WhereFilter.empty();
163
164@@ -47,8 +51,6 @@
165
166 df = DateUtils.getShortDateFormat(this);
167
168- final Spinner groupSeparators = (Spinner)findViewById(R.id.spinnerGroupSeparators);
169- groupSeparators.setSelection(1);
170 filter.put(new DateTimeCriteria(PeriodType.THIS_MONTH));
171
172 bPeriod = (Button)findViewById(R.id.bPeriod);
173@@ -67,6 +69,9 @@
174 public void onClick(View view) {
175 Spinner decimals = (Spinner)findViewById(R.id.spinnerDecimals);
176 Spinner decimalSeparators = (Spinner)findViewById(R.id.spinnerDecimalSeparators);
177+ Spinner groupSeparators = (Spinner)findViewById(R.id.spinnerGroupSeparators);
178+ Spinner fieldSeparators = (Spinner)findViewById(R.id.spinnerFieldSeparator);
179+ CheckBox includeHeader = (CheckBox)findViewById(R.id.checkboxIncludeHeader);
180
181 Intent data = new Intent();
182 filter.toIntent(data);
183@@ -74,6 +79,8 @@
184 data.putExtra(CSV_EXPORT_DECIMALS, 2-decimals.getSelectedItemPosition());
185 data.putExtra(CSV_EXPORT_DECIMAL_SEPARATOR, decimalSeparators.getSelectedItem().toString());
186 data.putExtra(CSV_EXPORT_GROUP_SEPARATOR, groupSeparators.getSelectedItem().toString());
187+ data.putExtra(CSV_EXPORT_FIELD_SEPARATOR, fieldSeparators.getSelectedItem().toString().charAt(1));
188+ data.putExtra(CSV_EXPORT_INCLUDE_HEADER, includeHeader.isChecked());
189
190 setResult(RESULT_OK, data);
191 finish();
192@@ -92,6 +99,52 @@
193 updatePeriod();
194 }
195
196+ @Override
197+ protected void onPause() {
198+ super.onPause();
199+ savePreferences();
200+ }
201+
202+ @Override
203+ protected void onResume() {
204+ super.onResume();
205+ restorePreferences();
206+ }
207+
208+ private void savePreferences() {
209+ Spinner decimals = (Spinner)findViewById(R.id.spinnerDecimals);
210+ Spinner decimalSeparators = (Spinner)findViewById(R.id.spinnerDecimalSeparators);
211+ Spinner groupSeparators = (Spinner)findViewById(R.id.spinnerGroupSeparators);
212+ Spinner fieldSeparators = (Spinner)findViewById(R.id.spinnerFieldSeparator);
213+ CheckBox includeHeader = (CheckBox)findViewById(R.id.checkboxIncludeHeader);
214+
215+ SharedPreferences.Editor editor = getPreferences(MODE_PRIVATE).edit();
216+
217+ editor.putInt(CSV_EXPORT_DECIMALS, decimals.getSelectedItemPosition());
218+ editor.putInt(CSV_EXPORT_DECIMAL_SEPARATOR, decimalSeparators.getSelectedItemPosition());
219+ editor.putInt(CSV_EXPORT_GROUP_SEPARATOR, groupSeparators.getSelectedItemPosition());
220+ editor.putInt(CSV_EXPORT_FIELD_SEPARATOR, fieldSeparators.getSelectedItemPosition());
221+ editor.putBoolean(CSV_EXPORT_INCLUDE_HEADER, includeHeader.isChecked());
222+
223+ editor.commit();
224+ }
225+
226+ private void restorePreferences() {
227+ Spinner decimals = (Spinner)findViewById(R.id.spinnerDecimals);
228+ Spinner decimalSeparators = (Spinner)findViewById(R.id.spinnerDecimalSeparators);
229+ Spinner groupSeparators = (Spinner)findViewById(R.id.spinnerGroupSeparators);
230+ Spinner fieldSeparators = (Spinner)findViewById(R.id.spinnerFieldSeparator);
231+ CheckBox includeHeader = (CheckBox)findViewById(R.id.checkboxIncludeHeader);
232+
233+ SharedPreferences prefs = getPreferences(MODE_PRIVATE);
234+
235+ decimals.setSelection(prefs.getInt(CSV_EXPORT_DECIMALS, 0));
236+ decimalSeparators.setSelection(prefs.getInt(CSV_EXPORT_DECIMAL_SEPARATOR, 0));
237+ groupSeparators.setSelection(prefs.getInt(CSV_EXPORT_GROUP_SEPARATOR, 1));
238+ fieldSeparators.setSelection(prefs.getInt(CSV_EXPORT_FIELD_SEPARATOR, 0));
239+ includeHeader.setChecked(prefs.getBoolean(CSV_EXPORT_INCLUDE_HEADER, true));
240+ }
241+
242 private void updatePeriod() {
243 DateTimeCriteria c = filter.getDateTime();
244 if (c == null) {
245
246=== modified file 'src/ru/orangesoftware/financisto/activity/MainActivity.java'
247--- src/ru/orangesoftware/financisto/activity/MainActivity.java 2010-09-12 11:06:23 +0000
248+++ src/ru/orangesoftware/financisto/activity/MainActivity.java 2010-09-18 00:44:43 +0000
249@@ -145,18 +145,20 @@
250 if (resultCode == RESULT_OK) {
251 WhereFilter filter = WhereFilter.fromIntent(data);
252 Currency currency = new Currency();
253+ char fieldSeparator = data.getCharExtra(CsvExportActivity.CSV_EXPORT_FIELD_SEPARATOR, ',');
254+ boolean includeHeader = data.getBooleanExtra(CsvExportActivity.CSV_EXPORT_INCLUDE_HEADER, true);
255 currency.symbol = "$";
256 currency.decimals = data.getIntExtra(CsvExportActivity.CSV_EXPORT_DECIMALS, 2);
257 currency.decimalSeparator = data.getStringExtra(CsvExportActivity.CSV_EXPORT_DECIMAL_SEPARATOR);
258 currency.groupSeparator = data.getStringExtra(CsvExportActivity.CSV_EXPORT_GROUP_SEPARATOR);
259- doCsvExport(filter, currency);
260+ doCsvExport(filter, currency, fieldSeparator, includeHeader);
261 }
262 }
263 }
264
265- private void doCsvExport(WhereFilter filter, Currency currency) {
266+ private void doCsvExport(WhereFilter filter, Currency currency, char fieldSeparaotr, boolean includeHeader) {
267 ProgressDialog d = ProgressDialog.show(this, null, getString(R.string.csv_export_inprogress), true);
268- new CsvExportTask(d, filter, currency).execute((String[])null);
269+ new CsvExportTask(d, filter, currency, fieldSeparaotr, includeHeader).execute((String[])null);
270 }
271
272 private void initialLoad() {
273@@ -499,16 +501,21 @@
274
275 private final WhereFilter filter;
276 private final Currency currency;
277+ private final char fieldSeparator;
278+ private final boolean includeHeader;
279
280- public CsvExportTask(ProgressDialog dialog, WhereFilter filter, Currency currency) {
281+ public CsvExportTask(ProgressDialog dialog, WhereFilter filter, Currency currency,
282+ char fieldSeparator, boolean includeHeader) {
283 super(MainActivity.this, dialog, null);
284 this.filter = filter;
285 this.currency = currency;
286+ this.fieldSeparator = fieldSeparator;
287+ this.includeHeader = includeHeader;
288 }
289
290 @Override
291 protected Object work(Context context, DatabaseAdapter db, String...params) throws Exception {
292- CSVExport export = new CSVExport(db, filter, currency);
293+ CSVExport export = new CSVExport(db, filter, currency, fieldSeparator, includeHeader);
294 return export.export();
295 }
296
297
298=== modified file 'src/ru/orangesoftware/financisto/export/CSVExport.java'
299--- src/ru/orangesoftware/financisto/export/CSVExport.java 2010-09-12 11:06:23 +0000
300+++ src/ru/orangesoftware/financisto/export/CSVExport.java 2010-09-18 00:44:43 +0000
301@@ -33,12 +33,21 @@
302
303 private final DatabaseAdapter db;
304 private final WhereFilter filter;
305- private final NumberFormat f;
306+ private final NumberFormat f;
307+ private final char fieldSeparator;
308+ private final boolean includeHeader;
309
310- public CSVExport(DatabaseAdapter db, WhereFilter filter, Currency currency) {
311+ public CSVExport(DatabaseAdapter db, WhereFilter filter, Currency currency,
312+ char fieldSeparator, boolean includeHeader) {
313 this.db = db;
314 this.filter = filter;
315 this.f = CurrencyCache.createCurrencyFormat(currency);
316+ this.fieldSeparator = fieldSeparator;
317+ this.includeHeader = includeHeader;
318+ }
319+
320+ public CSVExport(DatabaseAdapter db, WhereFilter filter, Currency currency) {
321+ this(db, filter, currency, ',', true);
322 }
323
324 @Override
325@@ -48,12 +57,17 @@
326
327 @Override
328 protected void writeHeader(BufferedWriter bw) throws IOException {
329- bw.write("date,time,account,amount,currency,category,parent,location,project,note\n");
330+ if (includeHeader) {
331+ Csv.Writer w = new Csv.Writer(bw).delimiter(fieldSeparator);
332+ w.value("date").value("time").value("account").value("amount").value("currency");
333+ w.value("category").value("parent").value("location").value("project").value("note");
334+ w.newLine();
335+ }
336 }
337
338 @Override
339 protected void writeBody(BufferedWriter bw) throws IOException {
340- Csv.Writer w = new Csv.Writer(bw).delimiter(',');
341+ Csv.Writer w = new Csv.Writer(bw).delimiter(fieldSeparator);
342 try {
343 HashMap<Long, Category> categoriesMap = db.getAllCategoriesMap(false);
344 Cursor c = db.getBlotter(filter);