Export to CSV

pull/30/head
Alinson S. Xavier 10 years ago
parent 02b3ea58cf
commit af0ef90e4d

@ -23,9 +23,12 @@ import android.app.AlertDialog;
import android.app.Fragment; import android.app.Fragment;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
@ -68,9 +71,11 @@ import org.isoron.uhabits.commands.ChangeHabitColorCommand;
import org.isoron.uhabits.commands.DeleteHabitsCommand; import org.isoron.uhabits.commands.DeleteHabitsCommand;
import org.isoron.uhabits.commands.UnarchiveHabitsCommand; import org.isoron.uhabits.commands.UnarchiveHabitsCommand;
import org.isoron.uhabits.helpers.ReminderHelper; import org.isoron.uhabits.helpers.ReminderHelper;
import org.isoron.uhabits.io.CSVExporter;
import org.isoron.uhabits.loaders.HabitListLoader; import org.isoron.uhabits.loaders.HabitListLoader;
import org.isoron.uhabits.models.Habit; import org.isoron.uhabits.models.Habit;
import java.io.File;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.LinkedList; import java.util.LinkedList;
@ -199,6 +204,12 @@ public class ListHabitsFragment extends Fragment
return true; return true;
} }
case R.id.action_export_csv:
{
onExportHabitsClick(selectedHabits);
return true;
}
} }
return false; return false;
@ -248,6 +259,7 @@ public class ListHabitsFragment extends Fragment
private ActionMode actionMode; private ActionMode actionMode;
private List<Integer> selectedPositions; private List<Integer> selectedPositions;
private DragSortController dragSortController; private DragSortController dragSortController;
private ProgressBar progressBar;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
@ -265,7 +277,7 @@ public class ListHabitsFragment extends Fragment
View view = inflater.inflate(R.layout.list_habits_fragment, container, false); View view = inflater.inflate(R.layout.list_habits_fragment, container, false);
tvNameHeader = (TextView) view.findViewById(R.id.tvNameHeader); tvNameHeader = (TextView) view.findViewById(R.id.tvNameHeader);
ProgressBar progressBar = (ProgressBar) view.findViewById(R.id.progressBar); progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
loader.setProgressBar(progressBar); loader.setProgressBar(progressBar);
adapter = new ListHabitsAdapter(getActivity()); adapter = new ListHabitsAdapter(getActivity());
@ -782,4 +794,43 @@ public class ListHabitsFragment extends Fragment
if (refreshKey == null) loader.updateAllHabits(true); if (refreshKey == null) loader.updateAllHabits(true);
else loader.updateHabit(refreshKey); else loader.updateHabit(refreshKey);
} }
private void onExportHabitsClick(final LinkedList<Habit> selectedHabits)
{
new AsyncTask<Void, Void, Void>()
{
String filename;
@Override
protected void onPreExecute()
{
progressBar.setIndeterminate(true);
progressBar.setVisibility(View.VISIBLE);
}
@Override
protected void onPostExecute(Void aVoid)
{
if(filename != null)
{
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.setType("application/zip");
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(filename)));
startActivity(intent);
}
progressBar.setVisibility(View.GONE);
}
@Override
protected Void doInBackground(Void... params)
{
CSVExporter exporter = new CSVExporter(activity, selectedHabits);
filename = exporter.writeArchive();
return null;
}
}.execute();
}
} }

@ -0,0 +1,184 @@
package org.isoron.uhabits.io;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import com.activeandroid.Cache;
import org.isoron.helpers.DateHelper;
import org.isoron.uhabits.models.Habit;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.TimeZone;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class CSVExporter
{
private List<Habit> habits;
private Context context;
private java.text.DateFormat dateFormat;
private List<String> generateDirs;
private List<String> generateFilenames;
private String basePath;
public CSVExporter(Context context, List<Habit> habits)
{
this.habits = habits;
this.context = context;
generateDirs = new LinkedList<>();
generateFilenames = new LinkedList<>();
basePath = String.format("%s/export/", context.getFilesDir());
dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
}
public String formatDate(long timestamp)
{
return dateFormat.format(new Date(timestamp));
}
public String formatScore(int score)
{
return String.format("%.2f", ((float) score) / Habit.MAX_SCORE);
}
private void writeScores(String dirPath, Habit habit) throws IOException
{
String path = dirPath + "scores.csv";
FileWriter out = new FileWriter(basePath + path);
generateFilenames.add(path);
String query = "select timestamp, score from score where habit = ? order by timestamp";
String params[] = { habit.getId().toString() };
SQLiteDatabase db = Cache.openDatabase();
Cursor cursor = db.rawQuery(query, params);
if(!cursor.moveToFirst()) return;
do
{
String timestamp = formatDate(cursor.getLong(0));
String score = formatScore(cursor.getInt(1));
out.write(String.format("%s,%s\n", timestamp, score));
} while(cursor.moveToNext());
out.close();
cursor.close();
}
private void writeCheckmarks(String dirPath, Habit habit) throws IOException
{
String path = dirPath + "checkmarks.csv";
FileWriter out = new FileWriter(basePath + path);
generateFilenames.add(path);
String query = "select timestamp, value from checkmarks where habit = ? order by timestamp";
String params[] = { habit.getId().toString() };
SQLiteDatabase db = Cache.openDatabase();
Cursor cursor = db.rawQuery(query, params);
if(!cursor.moveToFirst()) return;
do
{
String timestamp = formatDate(cursor.getLong(0));
Integer value = cursor.getInt(1);
out.write(String.format("%s,%d\n", timestamp, value));
} while(cursor.moveToNext());
out.close();
cursor.close();
}
private void writeFiles(Habit habit) throws IOException
{
boolean success;
String path = String.format("%s/", habit.name);
new File(basePath + path).mkdirs();
generateDirs.add(path);
writeScores(path, habit);
writeCheckmarks(path, habit);
}
private void writeZipFile(String zipFilename) throws IOException
{
FileOutputStream fos = new FileOutputStream(zipFilename);
ZipOutputStream zos = new ZipOutputStream(fos);
for(String filename : generateFilenames)
addFileToZip(zos, filename);
zos.close();
fos.close();
}
private void addFileToZip(ZipOutputStream zos, String filename) throws IOException
{
FileInputStream fis = new FileInputStream(new File(basePath + filename));
ZipEntry ze = new ZipEntry(filename);
zos.putNextEntry(ze);
int length;
byte bytes[] = new byte[1024];
while((length = fis.read(bytes)) >= 0)
zos.write(bytes, 0, length);
zos.closeEntry();
fis.close();
}
private void cleanup()
{
for(String filename : generateFilenames)
new File(basePath + filename).delete();
for(String filename : generateDirs)
new File(basePath + filename).delete();
new File(basePath).delete();
}
public String writeArchive()
{
String date = formatDate(DateHelper.getStartOfToday());
String zipFilename = String.format("%s/habits-%s.zip", context.getExternalCacheDir(), date);
try
{
for (Habit h : habits)
writeFiles(h);
writeZipFile(zipFilename);
cleanup();
}
catch (IOException e)
{
e.printStackTrace();
return null;
}
return zipFilename;
}
}

@ -21,6 +21,11 @@
android:title="@string/unarchive" android:title="@string/unarchive"
android:icon="@drawable/ic_action_unarchive_dark"/> android:icon="@drawable/ic_action_unarchive_dark"/>
<item
android:id="@+id/action_export_csv"
android:title="@string/export_to_csv"
android:showAsAction="never" />
<item <item
android:id="@+id/action_delete" android:id="@+id/action_delete"
android:title="@string/delete" android:title="@string/delete"

@ -21,7 +21,12 @@
android:title="@string/unarchive" android:title="@string/unarchive"
android:icon="@drawable/ic_action_unarchive_light"/> android:icon="@drawable/ic_action_unarchive_light"/>
<item
android:id="@+id/action_export_csv"
android:title="@string/export_to_csv" />
<item <item
android:id="@+id/action_delete" android:id="@+id/action_delete"
android:title="@string/delete" /> android:title="@string/delete" />
</menu> </menu>

@ -111,6 +111,7 @@
<string name="any_weekday">Weekdays</string> <string name="any_weekday">Weekdays</string>
<string name="any_day">Any day</string> <string name="any_day">Any day</string>
<string name="select_weekdays">Select days</string> <string name="select_weekdays">Select days</string>
<string name="export_to_csv">Export to CSV</string>
<string-array name="hints"> <string-array name="hints">
<item>@string/hint_drag</item> <item>@string/hint_drag</item>

Loading…
Cancel
Save