Android SQLite的基本使用、生成Excel文件保存到本地

news2024/9/28 18:46:55

1. Android SQLite的基本使用

在这里插入图片描述

1.1. SQLiteOpenHelper

  Android 底层已经通过一个SQLiteOpenHelper的抽象类将数据库的创建,以及修改,更新等都放在了里面。
要使用它必须实现它的OnCreate(SQLiteDatabase db),onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 方法。
  onCreate:当数据库第一次被建立的时候被执行,例如创建表,初始化数据等。
onUpgrade:当数据库需要被更新的时候执行,例如删除久表,创建新表。

1.2. 自定义辅助类

  我们要在Android中使用SQLite,自然要一个数据库辅助类来创建或打开数据库,这个辅助类继承自SQLiteOpenHelper类。除了必须重写SQLiteOpenHelper的两个抽象方法外,我们还要创建辅助类的构造方法。

/*
 * SqliteOpenHelper
 * 1.提供了onCreate(), onUpGrade()等创建数据库更新数据库的函数
 * 2.提供了获取数据库对象的函数
 */
public class MySqliteHelper extends SQLiteOpenHelper {

    /**
     * 构造函数
     * @param context 上下文对象
     * @param name 表示创建数据库的名称
     * @param factory 游标工厂
     * @param version 表示创建数据库的版本
     */
    public MySqliteHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    /**
     * 当数据库创建时回调的函数
     * @param db 数据库对象
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.i("TAG", "-------onCreate--------");
    }

    /**
     * 当数据库版本更新时回调的函数
     * @param db 数据库对象
     * @param oldVersion 数据库旧版本
     * @param newVersion 数据库新版本
     */
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.i("TAG", "-------onUpGrade-------");
    }

    /**
     * 当数据库打开时回调的函数
     * @param db 数据库对象
     */
    @Override
    public void onOpen(SQLiteDatabase db) {
        super.onOpen(db);
        Log.i("TAG", "-------onOpen-------");
    }
}

  onOpen 方法并不是必须重写的方法,是打开数据库会回调的函数,我们用 log 日志来监控数据库的状况。
  看到MySqliteHelper类的构造方法可以知道,我们要传入这几个参数比较麻烦,如果每次实例化都需要传入,不利于修改阅读,所以我们通常会创建一个常量类来保存数据库名,版本号这些常量。像如果以后版本号更新了,我们可以很简单的修改。

1.3. 常量类

  在这里我们先创建这几个常量。

public class Constant {
    public static final String DATABASE_NAME = "info.db"; //数据库名称
    public static final int DATABASE_VERSION = 1; //数据库版本
    public static final String TABLE_NAME = "person"; //表名
}

  既然这几个参数我们都已经确定好了,那就可以修改我们的构造函数啦。

    public MySqliteHelper(Context context) {
        super(context, Constant.DATABASE_NAME, null, Constant.DATABASE_VERSION);
    }

  现在只需要传入上下文即可,CursorFactory 为 null,数据库名称和版本号引用常量就可以啦。

1.4. 业务逻辑处理类

  我们的 MySqliteHelper 实现了数据库的建立和打开,相当于是一个持久化数据的存储,而 MainActivity 是整个页面数据的展示,我们为了降低耦合度(两者之间的密切关系程度,也可以理解为互相依赖的程度),通常建立一个 DbManager 类,来实现数据库的逻辑处理。

/**
 * 主要是对数据库操作的工具类
 */
public class DbManager {

    public enum Something {
        INSTANCE;
        private MySqliteHelper helper;

        public MySqliteHelper getInstance(Context context) {
            if (helper == null) {
                helper = new MySqliteHelper(context);
            }
            return helper;
        }
    }
}

  因为是对数据库的操作,所以我们这里用单例模式,这里我用了枚举的方法。对单例模式不了解的朋友,可以看看我的另一篇博客Java–单例模式。

1.5. 布局文件

  现在我们已经初步搭建好了数据库,可以测试数据库是否可以被创建。这里我是用 Button 的点击事件来操作,下面就是 xml 文件,只是很简单的布局,也是这个博客对数据库操作的主要内容。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <Button
            android:layout_weight="1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="创建数据库"
            android:onClick="createDb"
            android:background="#ff3" />

        <Button
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:id="@+id/btn_insert"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="插入数据"
            android:onClick="click"
            android:background="#ff3"
            android:layout_weight="1" />

        <Button
            android:layout_weight="1"
            android:id="@+id/btn_delete"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="删除数据"
            android:onClick="click"
            android:background="#ff3" />

    </LinearLayout>

    <LinearLayout
        android:layout_marginTop="60dp"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <Button
            android:layout_weight="1"
            android:id="@+id/btn_update"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="修改数据"
            android:onClick="click"
            android:background="#ff3" />

        <Button
            android:layout_weight="1"
            android:id="@+id/btn_deleteApi"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="删除数据api"
            android:onClick="onClick"
            android:background="#ff3"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"/>

        <Button
            android:layout_weight="1"
            android:id="@+id/btn_query"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="sql语句查询"
            android:onClick="click"
            android:background="#ff3" />

    </LinearLayout>

    <LinearLayout
        android:layout_marginTop="120dp"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <Button
            android:layout_weight="1"
            android:id="@+id/btn_insertApi"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="插入数据api"
            android:onClick="onClick"
            android:background="#ff3" />

        <Button
            android:layout_weight="1"
            android:id="@+id/btn_queryApi"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="API查询"
            android:onClick="onClick"
            android:background="#ff3"
            android:layout_marginRight="10dp"
            android:layout_marginLeft="10dp"/>

        <Button
            android:layout_weight="1"
            android:id="@+id/btn_updateApi"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="修改数据api"
            android:onClick="onClick"
            android:background="#ff3" />

    </LinearLayout>
</RelativeLayout>

在这里插入图片描述

1.5. 数据库表

  在我们的 SQLite 数据库中,数据的存储是以表的形式,所以在创建数据库的时候我们也应该创建一张数据表,学习过 SQL 语句的都知道要创建一张完整的数据表,需要表名和列名,而这些事我们有可能要去修改的,所以为了效率,我们应该把这些设置为常量去使用,前面我们建立了一个 Constant 类,让我们添加些数据进去:

public class Constant {
    public static final String DATABASE_NAME = "info.db"; //数据库名称
    public static final int DATABASE_VERSION = 1; //数据库版本
    public static final String TABLE_NAME = "person"; //表名
    public static final String _ID = "_id";
    public static final String NAME = "name";
    public static final String AGE = "age";
}

  可以看到,我们又添加了表名和三个字段,这样就方便我们日后修改。
  让我们回到 MySQLiteHelper 类:

    public void onCreate(SQLiteDatabase db) {
        Log.i("TAG", "-------onCreate--------");
        String sql = "create table " + Constant.TABLE_NAME + " (" +
                Constant._ID + " Integer primary key, " +
                Constant.NAME + " varchar(10)," +
                Constant.AGE + " Integer)";
        db.execSQL(sql);
    }

  execSQL(String sql) 是 SQLiteDatabase 类的执行 SQL 语句的方法,大家将刚才生成的 info.db 删除,再次运行,这样就能在创建数据库文件的时候创建一张 PERSON 的表啦。
  我们把生成的 info.db 导出到桌面或者你自己的某个硬盘目录下,用可视化数据库工具打开,你就可以看到数据库的信息,自然也能看到我们新创建的那张表。

1.6. SQL语句增删改查

  在 Android 中我们可以自己写 sql 语句去执行,但如果觉得写 sql 语句容易出错,也可以调用 api 中的方法。在 SQLite 中,查询操作是特别的,insert,update,delete都对数据做了修改,但 select 只返回结果,所以我们需要能接收这个结果,这样就不能使用 execSQL 方法啦。
  我们还有两个方法可以执行查询,分别是 rawQuery 和 query,query() 是 api 拼接 sql 语句,我们暂且不提。
  rawQuery(String sql, String[] selectionArgs),sql 就是执行的 select 语句,selectionArgs 是查询条件的占位符,如果没有占位符,就传入null即可,最后会返回一个 Cursor 对象,帮我们确定数据的位置。
  DBManager 类是我们用来管理数据库的工具类,execSQL() 是我们必须用到的方法,为了防止出错,我们应  该在 DBManager 类中写个方法来判断,同样 rawQuery() 也应该判断。

 public static void execSQL(SQLiteDatabase db, String sql) {
        if (db != null) {
            if (sql != null && !"".equals(sql)) {
                db.execSQL(sql);
            }
        }
    }

    public static Cursor selectDataBySql(SQLiteDatabase db, String sql, String[] selectionArgs) {
        Cursor cursor = null;
        if (db != null) {
            cursor = db.rawQuery(sql, selectionArgs);
        }
        return cursor;
    }

  相信大家都能够看懂,这里就不讲啦。
  rawQuery 是返回一个 Cursor 游标,那么我们自然需要把它转换为熟悉的 list 集合,首先我们要有存储数据的实体类,这就是 Java Bean 思想。

public class Person {
    private int _id;
    private String name;
    private int age;

    public Person(int _id, String name, int age) {
        this._id = _id;
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "_id=" + _id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public int get_id() {
        return _id;
    }

    public void set_id(int _id) {
        this._id = _id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

  有了这个 Person 类,我们就可以在 DBManager 中写从 Cursor 中读数据的方法啦。

public static List<Person> cursorTolist(Cursor cursor) {
        List<Person> list = new ArrayList<Person>();

        while (cursor.moveToNext()) {
            //getColumnIndex(String columnName) 根据参数中指定的字段名称获取字段下标
            int columnIndex = cursor.getColumnIndex(Constant._ID);
            //getInt(int columnIndex)根据参数中指定的字段下标 获取对应int类型的value
            int _id = cursor.getInt(columnIndex);

            String name = cursor.getString(cursor.getColumnIndex(Constant.NAME));
            int age = cursor.getInt(cursor.getColumnIndex(Constant.AGE));

            Person person = new Person(_id, name, age);
            list.add(person);
        }
        return list;
    }

  根据字段名获取字段下标,再得到字段的 value,懂得一点 Cursor 知识的朋友应该都能明白。

 public void click(View view) {
        switch (view.getId()) {
            case R.id.btn_insert :
                SQLiteDatabase db = helper.getWritableDatabase();
                for (int i = 1; i <= 30; i++) {
                    String sql1 = " insert into " + Constant.TABLE_NAME + " values(" + i + ",'张三" + i + "'," + i + ") ";
                    DbManager.execSQL(db, sql1);
                }
                db.close();
                break;
            case R.id.btn_update :
                db = helper.getWritableDatabase();
                String updatesql=" update "+ Constant.TABLE_NAME + " set " + Constant.NAME +
                       "='xiao' where " + Constant._ID + "=1";
                DbManager.execSQL(db,updatesql);
                db.close();
                break;
            case R.id.btn_delete :
                db = helper.getWritableDatabase();
                String deletesql = " delete from " + Constant.TABLE_NAME + " where " + Constant._ID + "=2";
                DbManager.execSQL(db,deletesql);
                db.close();
                break;
            case R.id.btn_query :
                db = helper.getWritableDatabase();
                String sql = "select * from " + Constant.TABLE_NAME;
                Cursor cursor = DbManager.selectDataBySql(db, sql, null);
                List<Person> list = DbManager.cursorTolist(cursor);
                for (Person p: list) {
                    Log.i("TAG", p.toString());
                }
                db.close();
                break;
        }
    }

  因为这个代码只是测试数据,所以就随便添加,只要实现功能即可。
  这些代码是很容易理解的,现在打开模拟器点击按钮来看看。
  我们可以看到表中已经有了30条数据,并且 id = 2的数据已经被删除了,id = 1的数据名字也已经别改成了 xiao,这说明我们的功能已经实现了。这里要注意的是,如果你按了几次 insert,会报错,因为 id 重复了,这并没什么。
  因为我们执行的 select 是查询全部信息,所以查询结果也显然成功啦。

1.7. API 操作

  数据库的增删改查需要正确的 SQL 语句,如果对 SQL 语句不熟练的用提供的 api 也是一样的。

1.7.1. insert

insert(String table, String nullColumnHack, ContentValues values);

  table:相信大家都能理解是数据表名。
  nullColumnStack:因为在 SQLite 中可以允许列中有 NULL,但不能整列都是NULL,这个值代表强行插入null值的数据列的列名,我们都是给 null 就可以了。
  values:代表一行记录的数据。insert 方法插入的一行记录使用ContentValues存放,我们看看它的说明。

private HashMap<String, Object> mValues;

  可以知道 ContentValues 是一个键为 String 的 HashMap集合,它提供了多种 put(String key, XXX value) (其中key为数据列的列名)方法用于存入数据,多种 getAsXxx(String key) 方法用于取出数据。
  insert 方法返回 long,代表新添记录的行号,该行号是一个内部直,与主键id无关,发生错误返回-1。

1.7.2. update

update(String table, ContentValues values, String whereClause, String[] whereArgs)

  table 与 values 和 insert 方法是一样的。
  whereClause:表示修改条件,满足该whereClause子句的记录将会被更新。
  whereArgs:表示修改条件的占位符,用于为whereArgs子句传递参数。
  update 方法返回一个 int,表示修改的数据条数。

1.7.3. delete

delete(String table, String whereClause, String[] whereArgs)

  table:代表想删除数据的表名。
  whereClause:满足该whereClause子句的记录将会被删除。
  whereArgs:用于为whereArgs子句传入参数。
与 update 方法中的格式是一样的。

1.7.4. query

query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)

  distinct:指定是否去除重复记录。
  table:执行查询数据的表名。
  columns:要查询出来的列名。
  selection:查询条件子句。
  selectionArgs:用于为selection子句中占位符传入参数值,值在数组中的位置与占位符在语句中的位置必须一致,否则就会有异常。
  groupBy:用于控制分组。
  having:用于对分组进行过滤。
  orderBy:用于对记录进行排序。
  limit:用于进行分页。
  最后返回 Cursor 游标。

public void onClick(View view) {
        switch(view.getId()) {
            case R.id.btn_insertApi :
                SQLiteDatabase db = helper.getWritableDatabase();

                ContentValues values = new ContentValues();
                values.put(Constant._ID, 2); //put(表示插入数据库的字段名称,表示插入该字段的具体值)
                values.put(Constant.NAME, "Lily");
                values.put(Constant.AGE, 15);

                long result = db.insert(Constant.TABLE_NAME, null, values);
                if (result > 0) {
                    Toast.makeText(this, "插入数据成功", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(this, "插入数据失败", Toast.LENGTH_SHORT).show();
                }
                db.close();
                break;
            case R.id.btn_updateApi :
                db = helper.getWritableDatabase();

                ContentValues cv = new ContentValues();
                cv.put(Constant.NAME, "cc");//put(表示需要修改的字段名称, 修改后的字段值)
//                int count = db.update(Constant.TABLE_NAME, cv, Constant._ID + "=3", null);
                int count = db.update(Constant.TABLE_NAME, cv, Constant._ID + "=?", new String[]{"3"});
                if (count > 0) {
                    Toast.makeText(this, "修改数据成功", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(this, "修改数据失败", Toast.LENGTH_SHORT).show();
                }
                db.close();
                break;
            case R.id.btn_deleteApi :
                db = helper.getWritableDatabase();

                int count2 = db.delete(Constant.TABLE_NAME, Constant._ID + "=?", new String[]{"1"});
                if (count2 > 0) {
                    Toast.makeText(this, "删除数据成功", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(this, "删除数据失败", Toast.LENGTH_SHORT).show();
                }
                db.close();
                break;

            case R.id.btn_queryApi :
                db = helper.getWritableDatabase();

                Cursor cursor = db.query(Constant.TABLE_NAME, null, Constant._ID + ">?",
                new String[]{"10"}, null, null, Constant._ID + " asc");
                List<Person> list = DbManager.cursorTolist(cursor);
                for (Person p : list) {
                    Log.i("TAG", p.toString());
                }
                db.close();
                break;
        }
    }

  这可以看到,在写查询条件的时候有两种写法:

db.update(Constant.TABLE_NAME, cv, Constant._ID + "=3", null);

db.update(Constant.TABLE_NAME, cv, Constant._ID + "=?", new String[]{"3"});

  这两种是完全一样的。
  并没有出现强退,我们看看数据表的变化。
  可以看到我们已经删除了 id = 1 的数据,并且以前 id = 2 被删除的数据也插入了新的,id = 3 的数据也被修改了,再看看查询。
  id > 10 的数据都被输出了,说明我们 api 的功能也都实现啦。

2. Android 生成Excel文件保存到本地

  可以下载下来修改直接用,该项目主要是依赖一个叫jxl.jar的包,导到项目中libs文件下加即可。
  下载地址:https://download.csdn.net/download/qq_36158551/89808728?spm=1001.2014.3001.5503
在这里插入图片描述

  逻辑代码

public class ExcelUtil {
	//内存地址
	public static String root = Environment.getExternalStorageDirectory()
			.getPath();

	public static void writeExcel(Context context, List<Order> exportOrder,
			String fileName) throws Exception {
		if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)&&getAvailableStorage()>1000000) {
			Toast.makeText(context, "SD卡不可用", Toast.LENGTH_LONG).show();
			return;
		}
		String[] title = { "订单", "店名", "电话", "地址" };
		File file;
//		File dir = new File(context.getExternalFilesDir(null).getPath());
		File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
		file = new File(dir, fileName + ".xls");
		if (!dir.exists()) {
			dir.mkdirs();
		}
		// 创建Excel工作表
		WritableWorkbook wwb;
		OutputStream os = new FileOutputStream(file);
		wwb = Workbook.createWorkbook(os);
		// 添加第一个工作表并设置第一个Sheet的名字
		WritableSheet sheet = wwb.createSheet("订单", 0);
		Label label;
		for (int i = 0; i < title.length; i++) {
			// Label(x,y,z) 代表单元格的第x+1列,第y+1行, 内容z
						// 在Label对象的子对象中指明单元格的位置和内容
			label = new Label(i, 0, title[i], getHeader());
			// 将定义好的单元格添加到工作表中
			sheet.addCell(label);
		}

		for (int i = 0; i < exportOrder.size(); i++) {
			Order order = exportOrder.get(i);

			Label orderNum = new Label(0, i + 1, order.id);
			Label restaurant = new Label(1, i + 1, order.restName);
			Label nameLabel = new Label(2,i+1,order.restPhone);
			Label address = new Label(3, i + 1, order.receiverAddr);
			
			sheet.addCell(orderNum);
			sheet.addCell(restaurant);
			sheet.addCell(nameLabel);
			sheet.addCell(address);
			Toast.makeText(context, "写入成功", Toast.LENGTH_LONG).show();
			
		}
		// 写入数据
		wwb.write();
		// 关闭文件
		wwb.close();
	}

	public static WritableCellFormat getHeader() {
		WritableFont font = new WritableFont(WritableFont.TIMES, 10,
				WritableFont.BOLD);// 定义字体
		try {
			font.setColour(Colour.BLUE);// 蓝色字体
		} catch (WriteException e1) {
			e1.printStackTrace();
		}
		WritableCellFormat format = new WritableCellFormat(font);
		try {
			format.setAlignment(jxl.format.Alignment.CENTRE);// 左右居中
			format.setVerticalAlignment(jxl.format.VerticalAlignment.CENTRE);// 上下居中
			// format.setBorder(Border.ALL, BorderLineStyle.THIN,
			// Colour.BLACK);// 黑色边框
			// format.setBackground(Colour.YELLOW);// 黄色背景
		} catch (WriteException e) {
			e.printStackTrace();
		}
		return format;
	}
	
	/** 获取SD可用容量 */
	private static long getAvailableStorage() {

		StatFs statFs = new StatFs(root);
		long blockSize = statFs.getBlockSize();
		long availableBlocks = statFs.getAvailableBlocks();
		long availableSize = blockSize * availableBlocks;
		// Formatter.formatFileSize(context, availableSize);
		return availableSize;
	}
}

3. Android SQLite及生成Excel文件保存到本地完整代码

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3.1. SqlActivity

package com.inspur.szyj.activity;

import android.database.Cursor;
import android.os.Bundle;
import android.view.View;
import android.widget.ListView;

import androidx.appcompat.app.AppCompatActivity;

import com.inspur.szyj.R;
import com.inspur.szyj.adapter.SqlAdapter;
import com.inspur.szyj.bean.PersonBean;
import com.inspur.szyj.helper.DateHelper;
import com.inspur.szyj.helper.db.DbService;
import com.inspur.szyj.util.ExcelUtil;

import java.util.ArrayList;
import java.util.List;

public class SqlActivity extends AppCompatActivity
        implements View.OnClickListener {
    private ListView lv;//控件
    private Cursor cursor;//数据源
    //自定义的封装类
    private DbService dbService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sql);
        findViewById(R.id.create).setOnClickListener(this);
        findViewById(R.id.update_db).setOnClickListener(this);
        findViewById(R.id.insert).setOnClickListener(this);
        findViewById(R.id.update).setOnClickListener(this);
        findViewById(R.id.select).setOnClickListener(this);
        findViewById(R.id.delete).setOnClickListener(this);
        findViewById(R.id.delete_all).setOnClickListener(this);
        findViewById(R.id.save_excel).setOnClickListener(this);
        lv = findViewById(R.id.lv);
        dbService = new DbService(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.create) {
            dbService.createDB();
        } else if (v.getId() == R.id.update_db) {
            dbService.updateDatabase();
        } else if (v.getId() == R.id.insert) {
            PersonBean personBean = new PersonBean();
            personBean.setName("张三");
            personBean.setIdCard("372929199901010101");
            personBean.setSignTime(DateHelper.getCurTime());
            personBean.setSignDate(DateHelper.getCurDate());
            dbService.insertDb(personBean);
        } else if (v.getId() == R.id.update) {
            dbService.updateDb();
        } else if (v.getId() == R.id.select) {
            List<PersonBean> personList = new ArrayList<>();
            cursor = dbService.queryDb();
            if (cursor != null) {
                //1, 游标向下移动一条数据   2, 判断当前移动到的数据是否存在
                while (cursor.moveToNext()) {
                    //获取指定的内容cursor.getString(列的编号, 编号是从0开始)
                    PersonBean personBean = new PersonBean();
                    //personBean.setName(cursor.getString(1));
                    int nameIndex = cursor.getColumnIndex(
                            "name");
                    personBean.setName(cursor.getString(nameIndex));
                    int idCardIndex = cursor.getColumnIndex(
                            "id_card");
                    personBean.setIdCard(cursor.getString(idCardIndex));
                    int signTimeIndex = cursor.getColumnIndex(
                            "sign_time");
                    personBean.setSignTime(cursor.getString(signTimeIndex));
                    int signDateIndex = cursor.getColumnIndex(
                            "sign_date");
                    personBean.setSignDate(cursor.getString(signDateIndex));
                    personList.add(personBean);
                }
                //关闭游标
                cursor.close();
            }
            SqlAdapter adapter = new SqlAdapter(this, personList);
            lv.setAdapter(adapter);
        } else if (v.getId() == R.id.delete) {
            dbService.deleteDb();
        } else if (v.getId() == R.id.delete_all) {
            dbService.deleteDbAll();
        } else if (v.getId() == R.id.save_excel) {
            try {
                List<PersonBean> personList2 = new ArrayList<>();
                cursor = dbService.queryDb();
                if (cursor != null) {
                    //1, 游标向下移动一条数据   2, 判断当前移动到的数据是否存在
                    while (cursor.moveToNext()) {
                        //获取指定的内容cursor.getString(列的编号, 编号是从0开始)
                        PersonBean personBean = new PersonBean();
                        //personBean.setName(cursor.getString(1));
                        int nameIndex = cursor.getColumnIndex(
                                "name");
                        personBean.setName(cursor.getString(nameIndex));
                        int idCardIndex = cursor.getColumnIndex(
                                "id_card");
                        personBean.setIdCard(cursor.getString(idCardIndex));
                        int signTimeIndex = cursor.getColumnIndex(
                                "sign_time");
                        personBean.setSignTime(cursor.getString(signTimeIndex));
                        int signDateIndex = cursor.getColumnIndex(
                                "sign_date");
                        personBean.setSignDate(cursor.getString(signDateIndex));
                        personList2.add(personBean);
                    }
                    //关闭游标
                    cursor.close();
                }
                ExcelUtil.writeExcel(this, personList2, "excelFile");
            } catch (Exception e) {
            }
        }
    }
}

3.2. activity_sql.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".activity.JsonActivity">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:layout_marginBottom="5dp"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <Button
            android:id="@+id/create"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="3dp"
            android:padding="3dp"
            android:text="创建数据库"
            android:textSize="13sp" />

        <Button
            android:id="@+id/update_db"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="3dp"
            android:padding="3dp"
            android:text="版本更新"
            android:textSize="13sp" />

        <Button
            android:id="@+id/insert"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="3dp"
            android:padding="3dp"
            android:text="插入数据"
            android:textSize="13sp" />

        <Button
            android:id="@+id/update"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="3dp"
            android:text="修改数据"
            android:textSize="13sp" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:layout_marginBottom="5dp"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <Button
            android:id="@+id/select"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="3dp"
            android:text="查询数据"
            android:textSize="13sp" />

        <Button
            android:id="@+id/delete"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="3dp"
            android:text="删除数据"
            android:textSize="13sp" />

        <Button
            android:id="@+id/delete_all"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="3dp"
            android:text="删除所有数据"
            android:textSize="13sp" />
        <Button
            android:id="@+id/save_excel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="3dp"
            android:text="保存excel"
            android:textSize="13sp" />
    </LinearLayout>

    <ListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:divider="@null" />
</LinearLayout>

3.3. DbService

package com.inspur.szyj.helper.db;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import com.inspur.szyj.bean.PersonBean;

/**
 * 自定义的封装类
 * 用来实现数据库的操作
 * @author zzs
 */
public class DbService {
    private Context context;
    private DbOpenHelper dbOpenHelper;

    public DbService(Context context) {
        this.context = context;
        dbOpenHelper = new DbOpenHelper(context);
    }

    //创建数据库
    public void createDB() {
        //打开数据库连接(数据库只有在执行次方法后, 数据库才会被创建)
        //底层已经做了实现:  如果数据库不存在, 创建数据库并且打开连接;
        // 如果数据库存在,直接打开数据库连接
        dbOpenHelper.getWritableDatabase();
    }

    //数据库版本更新
    public void updateDatabase() {
        dbOpenHelper.getWritableDatabase();
    }

    //插入数据
    public void insertDb(PersonBean personBean) {
        //打开连接()
        SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
//        //方式一
//        db.execSQL("insert into person(name,id_card,sign_time,sign_date) values('张三','372929199901010101','2024-03-23 34:23:32','2024-03-23')");
//        //方式二
//        db.execSQL("insert into person(name,id_card,sign_time,sign_date) values (?,?,?,?)",
//                new String[]{"李四", "372929199901010101",
//                        "2024-03-23 34:23:32", "2024-03-24"});
        /*
         * 方式三
         * 封装好的方法
         * table 表名
         * nullColumnHack 可以为空
         * 如果ContentValues为空:  insert into person() values(null)
         * values	值  ContentValues
         */
        ContentValues values = new ContentValues();
        //key:表中的字段     value:字段对应的内容
        values.put("name", personBean.getName());
        values.put("id_card",  personBean.getIdCard());
        values.put("sign_time",  personBean.getSignTime());
        values.put("sign_date",  personBean.getSignDate());
        db.insert("person", null, values);
    }

    //查询数据
    public Cursor queryDb() {
        SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
        //顺序
        //sql = "select * from person order by _id asc";
        //倒序
        //sql = "select * from person order by _id desc";
        //得到查询后的游标
        //Cursor cursor=sqLiteDatabases.rawQuery(sql,null);
        //Cursor cursor  = db.rawQuery("select * from person ", null);
        /**
         * distinct			是否去除重复
         * table			表名
         * columns			查询的列名   new String[]{"_id","name","id_card","amount"}
         * 可以为null, 代表查询所有数据
         * selection		where 后面的字句  _id = ?
         * selectionArgs	占位符的值   new String[]{"1"}
         * groupBy			分组
         * having			放置在where 后再次筛选
         * orderBy			排序
         * limit			区间(分页加载数据)
         */
        //Cursor cursor = db.query("person", null, null, null, null, null, null);
//        Cursor cursor = db.query("person",
//                null, "name = ?", new String[]{"张三"},
//                null, null, "name desc");
        Cursor cursor = db.query("person",
                null, null,null,
                null, null, "name asc");
        return cursor;
    }

    //修改数据
    public void updateDb() {
        SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
        //方式一
        //db.execSQL("update person set amount = ? where _id=?",
        // new String[]{"5000","2"});
        /**
         * 方式二
         * table		表名
         * values		contentValues 值
         * whereClause  where 字句之后的内容
         * whereArgs    占位符的取值
         */
        ContentValues values = new ContentValues();
        values.put("name", "小灰灰");
        db.update("person", values, "name = ?",
                new String[]{"张三"});
        db.close();
    }

    /**
     * 删除数据
     */
    public void deleteDb() {
        SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
        //方式一
        //db.execSQL("delete from person where _id  = 1");
        //方式二
        //table:表名   whereClause:where 字句之后的内容  whereArgs:占位符的取值
        //db.delete("person", "name=2", null);
        //方式三
        //String[] args2 = {"111", "222", "333"};
        //db.delete("person", "[name]=? and [id_card]=? and [sign_time]=?", args);
        String[] args = {"小灰灰"};
        db.delete("person", "[name]=?", args);
        db.close();
    }
    /**
     * 删除所有数据
     */
    public void deleteDbAll() {
        SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
        db.delete("person", null, null);
        db.close();
    }
}

3.4. DbOpenHelper

package com.inspur.szyj.helper.db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

/**
 * 数据库的创建和版本的更新
 * @author zzs
 *
 */
public class DbOpenHelper extends SQLiteOpenHelper {
    /**
     * 构造方法   初始数据库创建的必要参数
     * @param context    上下文对象
     * name		数据库的名称
     * factory   游标工厂   null
     * version   数据库的版本号
     */
    public DbOpenHelper(Context context) {
        super(context, "qf25", null, 1);
    }

    /**
     * 创建初始的数据表
     * 第一次创建数据库时被调用(只调用一次)
     * SQLiteDatabase db   数据库操作类
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table person(_id integer primary key autoincrement," +
                "name varchar(50),id_card varchar(500))");
        db.execSQL("alter table person add sign_time varchar(500)");
        db.execSQL("alter table person add sign_date varchar(500)");
        //db.execSQL("alter table person add amount integer");
    }

    /**
     * 更新数据库
     * 如果数据库的版本号发生变化后, 执行此方法
     * SQLiteDatabase db 	数据库操作类
     * int oldVersion		旧版本号
     * int newVersion       新版本号
     *
     */
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.i("info", "数据库更新了");
        db.execSQL("alter table person add amount integer");
    }

}

3.5. ExcelUtil

package com.inspur.szyj.util;

import android.content.Context;
import android.os.Environment;
import android.os.StatFs;
import android.widget.Toast;

import com.inspur.szyj.bean.OrderBean;
import com.inspur.szyj.bean.PersonBean;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.List;

import jxl.Workbook;
import jxl.format.Colour;
import jxl.write.Label;
import jxl.write.WritableCellFormat;
import jxl.write.WritableFont;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;

/**
 * Created by zzs on 2016/1/15.
 */
public class ExcelUtil {
    //内存地址
    public static String root = Environment.getExternalStorageDirectory()
            .getPath();

    public static void writeExcel(Context context, List<PersonBean> exportOrder,
                                  String fileName) throws Exception {
        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
                && getAvailableStorage() > 1000000) {
            Toast.makeText(context, "SD卡不可用", Toast.LENGTH_LONG).show();
            return;
        }
        String[] title = {"姓名", "身份证号", "签到时间", "签到日期"};
        File file;
		File dir = new File(context.getExternalFilesDir(null).getPath());
//        File dir = new File(Environment.getExternalStorageDirectory()
//                .getAbsolutePath()+ "/excelDirectory");
        file = new File(dir, fileName + ".xls");
        if (!dir.exists()) {
            dir.mkdirs();
        }
        // 创建Excel工作表
        WritableWorkbook wwb;
        OutputStream os = new FileOutputStream(file);
        wwb = Workbook.createWorkbook(os);
        // 添加第一个工作表并设置第一个Sheet的名字
        WritableSheet sheet = wwb.createSheet("订单", 0);
        Label label;
        for (int i = 0; i < title.length; i++) {
            // Label(x,y,z) 代表单元格的第x+1列,第y+1行, 内容z
            // 在Label对象的子对象中指明单元格的位置和内容
            label = new Label(i, 0, title[i], getHeader());
            // 将定义好的单元格添加到工作表中
            sheet.addCell(label);
        }
        for (int i = 0; i < exportOrder.size(); i++) {
            PersonBean order = exportOrder.get(i);
            Label orderNum = new Label(0, i + 1, order.getName());
            Label restaurant = new Label(1, i + 1, order.getIdCard());
            Label nameLabel = new Label(2, i + 1, order.getSignTime());
            Label address = new Label(3, i + 1, order.getSignDate());
            sheet.addCell(orderNum);
            sheet.addCell(restaurant);
            sheet.addCell(nameLabel);
            sheet.addCell(address);
            Toast.makeText(context, "写入成功", Toast.LENGTH_LONG).show();
        }
        // 写入数据
        wwb.write();
        // 关闭文件
        wwb.close();
    }

    public static WritableCellFormat getHeader() {
        WritableFont font = new WritableFont(WritableFont.TIMES, 10,
                WritableFont.BOLD);// 定义字体
        try {
            font.setColour(Colour.BLUE);// 蓝色字体
        } catch (WriteException e1) {
            e1.printStackTrace();
        }
        WritableCellFormat format = new WritableCellFormat(font);
        try {
            format.setAlignment(jxl.format.Alignment.CENTRE);// 左右居中
            format.setVerticalAlignment(jxl.format.VerticalAlignment.CENTRE);// 上下居中
            // format.setBorder(Border.ALL, BorderLineStyle.THIN,
            // Colour.BLACK);// 黑色边框
            // format.setBackground(Colour.YELLOW);// 黄色背景
        } catch (WriteException e) {
            e.printStackTrace();
        }
        return format;
    }

    /** 获取SD可用容量 */
    private static long getAvailableStorage() {
        StatFs statFs = new StatFs(root);
        long blockSize = statFs.getBlockSize();
        long availableBlocks = statFs.getAvailableBlocks();
        long availableSize = blockSize * availableBlocks;
        // Formatter.formatFileSize(context, availableSize);
        return availableSize;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2174446.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一些硬件知识(二十五)

cadence设置led颜色&#xff1a; 切换到Current propeties才会有颜色选选项&#xff0c;点击红色就可以选择其他的颜色&#xff1a; 手机字库是维修人员对FLASH MEMORY的俗称&#xff0c;其真实名字是闪速存储器&#xff0c;简称闪存&#xff0c;相当于手机的“硬盘”&#xff…

【Linux网络】详解TCP协议(3)

&#x1f389;博主首页&#xff1a; 有趣的中国人 &#x1f389;专栏首页&#xff1a; Linux网络 &#x1f389;其它专栏&#xff1a; C初阶 | C进阶 | 初阶数据结构 小伙伴们大家好&#xff0c;本片文章将会讲解 TCP的流量控制和滑动窗口 的相关内容。 如果看到最后您觉得这篇…

VB.net读写NDEF标签URI智能海报WIFI蓝牙连接

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 Public Class Form1Dim oldpicckey(0 To 5) As Byte 卡片旧密码Dim newpicckey(0 To 5) As Byte 卡片新密码Function GetTagUID() As StringDim status As ByteDim myctrlword As …

Android手机投屏方案实现方式对比

文章目录 1.概述2.术语解释2.1 miracast2.2 scrcpy2.4 Wifi Direct2.5 app_process 3.技术实现对比3.1 Miracast3.1.1 Miracast介绍3.1.2 Miracast原理3.1.3 Miracast优缺点分析 3.2 Scrcpy3.2.1 scrcpy 介绍3.2.2 scrcpy的实现原理3.2.3 scrcpy的优缺点分析 3.3 Google cast3.…

Nisshinbo日清纺pvs1114太阳模拟器手测

Nisshinbo日清纺pvs1114太阳模拟器手测

影响上证50股指期货价格的因素有哪些?

上证50股指期货&#xff0c;作为反映上海证券交易所最具代表性50只股票整体表现的期货合约&#xff0c;其价格同样受到一系列复杂因素的驱动。以下是对影响上证50股指期货价格的主要因素进行的详细分析。 因素一、期货合约的供求关系 股指期货市场是一个由多头和空头双方共同…

关于AI副业,能说的都说了(最核心3大赛道、机会、方向)

AI&#xff0c;是生产力工具~ AI&#xff0c;也是焦虑和痛点 一直有小伙伴在问AI副业的事儿&#xff0c;之前也分享过很多。 但是&#xff0c;很多人对AI于副业的作用&#xff0c;过于表面和形式&#xff0c;所以&#xff0c;狂金来叨叨一下最核心的3大赛道&#xff0c;希望…

腾讯云SDK购买流程

音视频终端 SDK 需购买对应 License/套餐获得使用授权&#xff0c;本文将对购买 License/套餐的操作进行详细指引。 您可首先参考计费概述 确认您需要购买的内容&#xff0c;随后参考本文进行购买。本文仅提供 SDK 授权费用所需资源的购买&#xff0c;如果您需要使用其他相关云…

深入浅出MySQL事务处理:从基础概念到ACID特性及并发控制

1、什么是事务 在实际的业务开发中&#xff0c;有些业务操作要多次访问数据库。一个业务要发送多条SQL语句给数据库执行。需要将多次访问数据库的操作视为一个整体来执行&#xff0c;要么所有的SQL语句全部执行成功。如果其中有一条SQL语句失败&#xff0c;就进行事务的回滚&a…

回答网友一个数据显示的问题

事情是这个样子的 俺在一个C# 群里&#xff0c;一个问:"打开form2&#xff0c;可以同步显示form1的表格内容&#xff0c;在form2增删改表格内容之后&#xff0c;可以同步到form1中"。 俺 打开 delphi 放了几个 数据敏感 控件&#xff0c;演示了一下。还说了 一行…

Windows环境下训练开源图像超分项目 ECBSR 教程

ECBSR 介绍 ECBSR&#xff08;Edge-oriented Convolution Block for Real-time Super Resolution&#xff09;是一种针对移动设备设计的轻量级超分辨率网络。它的核心是一种可重参数化的构建模块&#xff0c;称为边缘导向卷积块&#xff08;ECB&#xff09;&#xff0c;这种模…

数集相等定义凸显“R各元x的对应x+1的全体=R”是几百年重大错误

黄小宁 变量x所取各数也均由x代表&#xff0c;x代表其变域&#xff08;x所有能取的数组成的集&#xff09;内任一元。设集A&#xff5b;x&#xff5d;表A各元均由x代表&#xff0c;&#xff5b;x&#xff5d;中变量x的变域是A。其余类推。因各数x可是数轴上点的坐标所以x∈R变换…

详解ES5中的数组方法

7.9 ES5中的数组方法 ECMAScript 5定义了9个新的数组方法来遍历、映射、过滤、检测、简化、搜索数组。 7.9.1 forEach() 7.9.2 map() 将调用的数组的每个元素传递给指定的函数&#xff0c;并返回一个数组&#xff0c;包含函数的返回值。 例如数组的每个元素的立方&#xf…

基于SpringBoot+Vue的大学生勤工助学兼职管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

【优选算法】(第八篇)

目录 串联所有单词的⼦串&#xff08;hard&#xff09; 题目解析 讲解算法原理 编写代码 最⼩覆盖⼦串&#xff08;hard&#xff09; 题目解析 讲解算法原理 编写代码 串联所有单词的⼦串&#xff08;hard&#xff09; 题目解析 1.题目链接&#xff1a;. - 力扣&#…

防砸安全鞋这样挑,舒适又安心!

在复杂多变的工作环境中&#xff0c;安全始终放在首位&#xff0c;特别是对于那些在工地、车间等危险环境中工作的朋友们来说&#xff0c;一双好的防砸安全鞋无疑是工作中的“守护神”。然而&#xff0c;市面上的防砸安全鞋种类繁多&#xff0c;如何挑选一双既舒适又安心的鞋子…

unreal engine5制作动作类游戏时,我们使用刀剑等武器攻击怪物或敌方单位时,发现攻击特效、伤害等没有触发

UE5系列文章目录 文章目录 UE5系列文章目录前言一、问题分析二、解决方法1. 添加项目设置碰撞检测通道2.玩家角色碰撞设置3.怪物角色碰撞预设 最终效果 前言 在使用unreal engine5制作动作类游戏时&#xff0c;我们使用刀剑等武器攻击怪物或敌方单位时&#xff0c;发现攻击特效…

10.C++程序中的循环语句

C中提供了三种循环语句&#xff08;for循环&#xff0c;while循环以及do-while循环)来使程序员可以更方便地对数据进行迭代操作。 if语句 for语句的格式为&#xff1a; for(初始化语句&#xff1b;循环条件&#xff1b;迭代语句&#xff09; &#xff5b; 代码块 &#x…

网上找旅游搭子靠谱吗?分享国庆与旅行搭子出行的冒险记

国庆将至&#xff0c;我那颗渴望旅行的心愈发躁动不安。一直想在这个难得的假期里去领略祖国的大好河山&#xff0c;思来想去&#xff0c;决定去神秘而美丽的张家界。然而&#xff0c;身边的朋友不是已有安排&#xff0c;就是对这个目的地不感兴趣。无奈之下&#xff0c;我只好…

ArcGIS与ArcGIS Pro去除在线地图服务名单

我们之前给大家分享了很多在线地图集&#xff0c;有些地图集会带有制作者信息&#xff0c;在布局制图的时候会带上信息影响出图美观。 一套GIS图源集搞定&#xff01;清新规划底图、影像图、境界、海洋、地形阴影图、导航图 比如ArcGIS&#xff1a; 比如ArcGIS Pro&#xff1a…