關於「備份」這件事情,除了雲端備份之外,我們在android中常見的還有Excel備份。
在java中備份是用到「jxl.jar」這個API,
關於這個API的下載可以參考這裡,而文件可以看這裡。
網路上有非常多的人實做這個應用,今天我們來為了android來實做,
首先先來試著想想android對於備份的應用怎麼做,使用流程如下:
在java中備份是用到「jxl.jar」這個API,
關於這個API的下載可以參考這裡,而文件可以看這裡。
網路上有非常多的人實做這個應用,今天我們來為了android來實做,
首先先來試著想想android對於備份的應用怎麼做,使用流程如下:
- 產生資料。
- 存入SQLite。
- 修改資料:
- 提取 SQLite中 對應的資料。
- 進行資料修改。
- 存入SQLite,覆蓋至對應的位置。
- 備份資料:
- 建立Excel檔案(.xls)。
- 建立 Excel檔案的工作表與建立第一列的欄位(通常Excel都會這樣做吧?)
- 提取SQLite中所有資料。
- 將提取出來的資料分批存入Excel檔案中。
要注意的是,jxl這個API裡面,.write()這個方法必須在最後調用,所以在範例中小書把他放到最後一個,寫完就關閉了這樣。
目前沒有做.xls檔案查詢的功能,有幾個理由:
- 要看這檔案的人,會透過M$的專門軟體來開啟,而且也已經有許多人開發了相對應的檢視軟體了。
- 我們對SQLite的操作比較瞭解,而這個API提供的方法不能確定其是否適合存取交替運作。
所以我們把.xls檔案的操作專注在「將SQLite的內容整理並複製置.xls檔案中」。
其實做的code如下,首先,我們必須增加能夠外部存取的權限:
接著,這是layout的內容:
然後,我們寫入兩個class,分別是databaase和excel所封裝起來的class:
最後,是main class,其中的流程是這樣的:
其檔案可以從SD卡的ExcelTest資料夾中找到.db3和.xls檔。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="exceltest.susan.idea"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:label="@string/app_name"
android:name=".ExcelTestActivity" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
接著,這是layout的內容:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="@+id/textView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:text="Test" />
</ScrollView>
然後,我們寫入兩個class,分別是databaase和excel所封裝起來的class:
package exceltest.susan.idea;
import java.sql.Timestamp;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DatabaseForExcelTest {
private static final String TAG = DatabaseForExcelTest.class.getSimpleName();
static final int VERSION = 1;
static final String DATABASE = android.os.Environment
.getExternalStorageDirectory().getAbsolutePath()
+ "/ExcelTest/database.db3";
static final String TABLE = "tableOfthisDataBase";
/**
* "date", "bssid", "ssid","level"
*/
public static final String[] KEY_COLUMNS = { "date", "bssid", "ssid",
"level" };
private static class DbHelper extends SQLiteOpenHelper {
public DbHelper(Context context) {
super(context, DATABASE, null, VERSION);
}
@Override
// 只會被呼叫一次,在第一次資料庫建立的時候
public void onCreate(SQLiteDatabase db) {
Log.i(TAG, "Creating database: " + DATABASE);
db.execSQL(getCreateSQL());
}
public String getCreateSQL() {
StringBuffer mStringBuffer = new StringBuffer();
mStringBuffer.append("CREATE TABLE IF NOT EXISTS " + TABLE + " ("
+ "_id" + " INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "
+ KEY_COLUMNS[0]
+ " TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,");
for (int n = 1; n < KEY_COLUMNS.length; n++) {
mStringBuffer.append(KEY_COLUMNS[n] + " TEXT, ");
}
mStringBuffer.delete(mStringBuffer.length() - 2,
mStringBuffer.length());// 刪除", "
mStringBuffer.append(");");
return mStringBuffer.toString();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
db.execSQL("DROP TABLE IF EXISTS " + TABLE);
this.onCreate(db);
}
}
private final DbHelper dbHelper;
private SQLiteDatabase db;
public DatabaseForExcelTest(Context context) {
dbHelper = new DbHelper(context);
Log.i(TAG, "Initialized database in Constructor of DB");
}
public DatabaseForExcelTest openToWrite() throws SQLException {
db = dbHelper.getWritableDatabase(); // 若資料庫存在則開啟;若不存在則建立一個新的
return this;
}
public DatabaseForExcelTest openToRead() throws SQLException {
db = dbHelper.getReadableDatabase(); // 若資料庫存在則開啟;若不存在則建立一個新的
return this;
}
public void close() {
dbHelper.close();
}
/** 添加資料 */
public void insert(ContentValues values) throws SQLException {
db.insertOrThrow(TABLE, null, values);
Log.i(TAG, "insert data into db");
}
/**
* 更新資料(測試)
*
* @param column
* 輸入欄位名稱
* @param oldValue
* 輸入欄位內欲查詢的變數
* @param newValue
* 輸入要更新的值
*/
public void update(String column, String oldValue, ContentValues newValue)
throws SQLException {
db.update(TABLE, newValue, column + "=" + oldValue, null);
}
/**
* 刪除資料(測試)
*
* @param column
* 輸入欄位名稱
* @param value
* 輸入欄位內欲查詢的變數
*/
public void deleteData(String column, String value) throws SQLException {
db.delete(TABLE, column + "=" + value, null);
}
/**
* 獲得資料(測試)
*
* @param column
* 輸入欄位名稱
* @param value
* 輸入欄位內欲查詢的變數
*/
public Cursor getData(String column, String value) {
String cmd = "SELECT * FROM " + TABLE + " WHERE " + column + "="
+ value;
return db.rawQuery(cmd, null);
}
/** 獲得全部資料 */
public Cursor getAll() {
// return db.rawQuery("SELECT * FROM " + TABLE, null);
return db.query(TABLE, null, null, null, null, null, null);
}
/** 依照時間間隔獲取資料 */
public Cursor getIntervalData(Timestamp from, Timestamp to) {
String cmd = "SELECT * FROM " + TABLE + " WHERE (" + KEY_COLUMNS[0]
+ " >= '" + from.toString() + "') AND (" + KEY_COLUMNS[0]
+ " <= '" + to.toString() + "')";
return db.rawQuery(cmd, null);
}
/** 清除全部的資料 */
public boolean clearAll() {
return db.delete(TABLE, null, null) > 0;
}
}
package exceltest.susan.idea;
import java.io.File;
import java.io.IOException;
import jxl.Workbook;
import jxl.format.Colour;
import jxl.read.biff.BiffException;
import jxl.write.Label;
import jxl.write.WritableCellFormat;
import jxl.write.WritableFont;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
import jxl.write.biff.RowsExceededException;
/** 參考:http://jexcelapi.sourceforge.net/resources/javadocs/current/docs/ */
public class ExcelHelper {
String path, fileName;
String[] labelNames;
WritableWorkbook mWritableWorkbook;
Workbook mWorkbook;
String EXCEL_PATH;
static WritableCellFormat mWritableCellFormat;
/** 開啟一個可寫入的excel檔案,注意最後必須調用closeExcelWritableWorkbook以完成寫入。 */
public boolean createExcelWritableWorkbook(String path, String fileName
) {
this.path = path;
this.fileName = fileName + ".xls";
EXCEL_PATH = this.path + "/" + this.fileName;
try {
// 打开文件
File dir = new File(path);
if (!dir.exists()) // true if this file exists, false otherwise.
{
dir.mkdir();// true if the directory has been created, false
// otherwise
}// 如果資料夾不存在則創立一個資料夾..
mWritableWorkbook = Workbook.createWorkbook(new File(EXCEL_PATH));
return true;
} catch (Exception e) {
System.out.println(e);
return false;
}
}
// public boolean getExcelBook() {
//
// if(mWritableWorkbook!=null){
// try {
// mWritableWorkbook.close();
// } catch (WriteException e) {
// e.printStackTrace();
// return false;
// } catch (IOException e) {
// e.printStackTrace();
// return false;
// }
// }
//
// try {
// mWorkbook = Workbook.getWorkbook(new File(EXCEL_PATH));
// return true;
// } catch (BiffException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
// return false;
// }
/** 關閉excel檔案,很重要!最後一定要執行 */
public boolean close() {
if (mWritableWorkbook != null) {
try {
wrriteExcelWritableWorkbook();
mWritableWorkbook.close();
return true;
} catch (WriteException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
if(mWorkbook!=null){
mWorkbook.close();
}
return false;
}
public WritableSheet getOrCreateExcelSheet(String sheetName) {
// 產生excel中的工作表
if (mWritableWorkbook != null) {
WritableSheet sheet = mWritableWorkbook.getSheet(sheetName);
if (sheet == null) {
sheet = mWritableWorkbook.createSheet(sheetName, 0);
}
return sheet;
}
return null;
}
/**放置文字至指定工作表中。*/
public boolean putData(WritableSheet sheet, int c, int r,
String lableString, WritableCellFormat mWritableCellFormat) {
Label label;
if (mWritableCellFormat != null) {
label = new Label(c, r, lableString, mWritableCellFormat);
} else {
label = new Label(c, r, lableString);
}
try {
sheet.addCell(label);
return true;
} catch (RowsExceededException e) {
e.printStackTrace();
} catch (WriteException e) {
e.printStackTrace();
}
return false;
}
/**放置數字至指定工作表中。*/
public boolean putData(WritableSheet sheet, int c, int r,
double numberDouble, WritableCellFormat mWritableCellFormat) {
jxl.write.Number number;
if (mWritableCellFormat != null) {
number = new jxl.write.Number(c, r, numberDouble,
mWritableCellFormat);
} else {
number = new jxl.write.Number(c, r, numberDouble);
}
try {
sheet.addCell(number);
return true;
} catch (RowsExceededException e) {
e.printStackTrace();
} catch (WriteException e) {
e.printStackTrace();
}
return false;
}
private boolean wrriteExcelWritableWorkbook() {
try {
mWritableWorkbook.write();
return true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
/**
* 設定表格的樣式。參考:http://jexcelapi.sourceforge.net/resources/javadocs/current/
* docs/
*/
public static WritableCellFormat putWritableCellFormat(
WritableFont.FontName writableFont, int paintSize, Colour mColour) {
if (mWritableCellFormat == null) {
mWritableCellFormat = new WritableCellFormat();
}
WritableFont chFont11w = new WritableFont(writableFont, paintSize);
/*
* WritableCellFormat cellFormat1 = new WritableCellFormat ();
* cellFormat1.setFont(chFont11w);
* cellFormat1.setBackground(Colour.DARK_GREEN);
* cellFormat1.setAlignment(Alignment.CENTRE);
* cellFormat1.setBorder(Border.ALL, BorderLineStyle.THIN,
* Colour.GRAY_80);
*/
try {
chFont11w.setColour(mColour);
} catch (WriteException e) {
e.printStackTrace();
}
mWritableCellFormat.setFont(chFont11w);
return mWritableCellFormat;
}
}
最後,是main class,其中的流程是這樣的:
- 增新資料,存入SQLite。
- 顯示資料,這邊是多餘的動作。
- 將資料從SQLite讀出來,再置入Excel當中。
package exceltest.susan.idea;
//生成Excel的类
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.TimeZone;
import jxl.format.Colour;
import jxl.write.WritableFont;
import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.os.Bundle;
import android.widget.TextView;
public class ExcelTestActivity extends Activity {
TextView mTextView;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mTextView = (TextView) this.findViewById(R.id.textView);
createTestingDataToSQLite(50);//增新n筆資料
showDataBase();//顯示資料,這邊顯示的資料應該會被蓋過去。
saveDataToExcelFromDatabase();//儲存資料
}
/** 建立測試檔案 */
private void createTestingDataToSQLite(int number) {
DatabaseForExcelTest db = new DatabaseForExcelTest(this);
db.openToWrite();
db.clearAll();//先做一個清空的動作。
Calendar c = Calendar.getInstance();
c.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));// 設定時區為台灣時間。
Timestamp timestamp;
ContentValues contentValues = new ContentValues();
for (int n = 0; n < number; n++) {
timestamp = new Timestamp(c.getTimeInMillis());// 先行建立,於輸入database時置入
putDatabaseValue(db, contentValues, timestamp,
"BSSID" + n, "SSID" + n, "LEVEL" + n);
}
db.close();
}
/** 顯示database中的檔案內容 */
private void showDataBase() {
DatabaseForExcelTest db = new DatabaseForExcelTest(this);
db.openToRead();
Cursor mCursor = db.getAll();
mCursor.moveToFirst();
do {
mTextView.append("顯示database資訊:");
mTextView
.append("\nBSSID:"
+ mCursor.getString(mCursor
.getColumnIndex(DatabaseForExcelTest.KEY_COLUMNS[1])));
mTextView
.append("\nSSID:"
+ mCursor.getString(mCursor
.getColumnIndex(DatabaseForExcelTest.KEY_COLUMNS[2])));
mTextView
.append("\nLEVEL:"
+ mCursor.getString(mCursor
.getColumnIndex(DatabaseForExcelTest.KEY_COLUMNS[3])));
} while (mCursor.moveToNext());
db.close();
}
/** 顯示database中的檔案內容 */
private void saveDataToExcelFromDatabase() {
mTextView.setText("儲存資料...");
final String path = android.os.Environment
.getExternalStorageDirectory().getAbsolutePath() + "/ExcelTest";// 路徑名稱
final String name = "ExcelTest";// 檔案名稱,不用加上副檔名
final String nameOfSheet = "第一頁";// 工作表名稱
ExcelHelper mExcelHelper = new ExcelHelper();
if (mExcelHelper.createExcelWritableWorkbook(path, name)) {//如果開啟成功
for (int n = 0; n < DatabaseForExcelTest.KEY_COLUMNS.length-1; n++) {
mExcelHelper.putData(mExcelHelper
.getOrCreateExcelSheet(nameOfSheet), n, 0,
DatabaseForExcelTest.KEY_COLUMNS[n+1], ExcelHelper
.putWritableCellFormat(WritableFont.TIMES, 16,
Colour.BLACK));
//這個for裡面,注意為了不要獲取time的資料欄位所做了+1-1等更動。
}
}
//打開database
DatabaseForExcelTest db = new DatabaseForExcelTest(this);
db.openToRead();
Cursor mCursor = db.getAll();//獲得所有內容
mCursor.moveToFirst();
String[] showInfo = { "\nBSID:", "\nSSID:", "\nLEVEL:" };
int inSheetRow=1;//因為第0列顯示的是欄位名稱
do {
mTextView.append("\n顯示database資訊:");
for (int n = 0; n < DatabaseForExcelTest.KEY_COLUMNS.length-1; n++) {
//顯示資訊
mTextView
.append(showInfo[n]
+ mCursor.getString(mCursor
.getColumnIndex(DatabaseForExcelTest.KEY_COLUMNS[n+1])));
//將資訊儲存至excel
mExcelHelper
.putData(
mExcelHelper.getOrCreateExcelSheet(nameOfSheet),
n,
inSheetRow,
mCursor.getString(mCursor
.getColumnIndex(DatabaseForExcelTest.KEY_COLUMNS[n+1])),
ExcelHelper.putWritableCellFormat(
WritableFont.TIMES, 30, Colour.BLACK));
//這個for裡面,注意為了不要獲取time的資料欄位所做了+1-1等更動。
}
inSheetRow++;//移到下一個row
} while (mCursor.moveToNext());
mExcelHelper.close();//寫入,關閉excel。
mTextView.append("\n完畢!");
db.close();
}
/**添加一筆資料至database*/
private void putDatabaseValue(DatabaseForExcelTest database,
ContentValues contentValues, Timestamp timestamp, String bssid,
String ssid, String level) {
// contentValues.clear();
contentValues.put(DatabaseForExcelTest.KEY_COLUMNS[0],
timestamp.toString());
contentValues.put(DatabaseForExcelTest.KEY_COLUMNS[1], bssid);
contentValues.put(DatabaseForExcelTest.KEY_COLUMNS[2], ssid);
contentValues.put(DatabaseForExcelTest.KEY_COLUMNS[3], level);
database.insert(contentValues);
}
}
其檔案可以從SD卡的ExcelTest資料夾中找到.db3和.xls檔。
您好
回覆刪除請問用您的ExcelTest.apk就可以將資料匯出至exceltest內
但是用上面的程式...就會顯示很抱歉...已停止...就不能執行了...請問這是什麼地方我沒有注意到
那可能是被我玩壞了。XD
回覆刪除你可以依照下面步驟檢查:
1.專案裡面的libs有沒有jxl.jar檔
2.檢查專專案沒有寫入讀取sd卡的權限
3.檢查看有沒有lose掉上面有的程式碼
如果是程式碼直接copy的話,沒有error的話,
可能就要請你給我看一下logcat顯示的錯誤訊息是什麼了。
謝謝您的回覆
刪除1.有的(用您的連結下戴)
2.這樣子對嗎?
在AndroidManifest.xml內
android:versionName="1.0" android:installLocation="auto">
3.只有第二個與您不同
第一個是AndroidManifest.xml
第二個是layout->activity_main.xml....這兒與您不同
第三個是DatabaseForExcelTest.java
第四個是ExcelHelper.java
第五個是ExcelTestActivity.java
網頁上面共提供了五個
我試了三次都是這樣子
顯示很抱歉...已停止...就不能執行了
所以才很甩冒昧請教您
我想...可以給我看error 的log訊息嗎??
刪除可能要知道比較詳細的訊息會有辦法debug
話說..
我剛剛想到, libs的jxl.jar有import進去嗎??
您好:
刪除我是自行將jxl.jar檔案直接copy到libs內
您說的import是如何操作才是
感謝您的回覆
有機會應該來做一篇imprort的方法,謝謝你的提醒。
刪除你可以先看這個:
http://cw1057.blogspot.tw/2011/12/android-jar-3rd-party-library.html
希望對你有幫助。
我做了一份整理:
刪除http://androidsusan.blogspot.tw/2013/04/import-jar.html
希望對你有幫助。