当ブログは福岡を中心とした都市の再開発や都市政策の紹介、考察を行うことをメインとしていますが、今回の記事では、本業であるアプリ・Webエンジニアとして作成したコードの保存用として記事を作成しております。予めご了承ください。
はじめに
データ一覧を表示させるアプリではそのデータからCSVを生成し、メールやラインに送信する機能がついているものが多いです。
CSVファイルはエクセルとの互換性も高く、大量のデータを一度に処理することに長けています。
今回はOpenCsvと呼ばれるJavaのライブラリを利用してKotlinアプリ内でCSVファイルを作成し、SNSなどに送信するまでの実装を紹介します。
事前準備(ライブラリを追加)
Gradle Scripts/build.gradle(.app)に以下を追加
バージョンは適宜変更してください。(公式サイト)
dependencies {
implementation 'com.opencsv:opencsv:5.6'
}
ファイル構成
- Csv
- OpenCsv.kt (CSVファイル作成クラス)
- DataForCsv.kt (CSVのカラム設定クラス)
- MainActivity.kt (CSVファイル作成実行・送信するアクティビティ)
コード
OpenCsv.kt (CSVファイル作成クラス)
class OpenCsv {
/* Csvファイルを作成するクラス
* - data ・・・ Csvに書き込むデータのリスト
* UserResponseはユーザー情報が入っているデータクラスの想定です。任意で変更してください。
* - activity ・・・ 呼び出し元のアクティビティ
*/
fun writeCsv(data: ArrayList<UserResponse>, activity: AppCompatActivity) : File? {
try {
// csvFileを作成
val file = File(activity.getExternalFilesDir(null), getFileName())
val fileOutputStream = FileOutputStream(file)
/*
* 文字コードの指定
* エクセルやスプレットシートではCSVファイルを文字コード"Shift_JIS"で読み込む設定になっています。
* 文字化けの要因になるのでCSVの利用想定に合わせてUTF-8などに変更してください。
*/
val writer = OutputStreamWriter(fileOutputStream, "Shift_JIS")
val csvWriter = StatefulBeanToCsvBuilder<DataForCsv>(writer).build()
// カラム名を挿入(一番上の行の列名)
csvWriter.write(
DataForCsv(
"ユーザー名",
"誕生日"
)
)
// ArrayList<UserResponse>の中身を取り出してCSVに一行ずつ挿入します
for (i in data) {
csvWriter.write(
i.name?.let {
DataForCsv(
it,
i.birthDay
)
}
)
}
writer.close()
return file
} catch (e: Exception) {
Log.e("CsvMakingFailed", e.toString())
// ここにファイル作成失敗時のエラー処理を記載
return null
}
}
/*
* ファイル名を取得する。ファイル名が被らないように、秒単位の日時を入れています。
* return ex) NewCsv2022-4-12-14-23-6.csv
*/
private fun getFileName() : String {
val calendar = Calendar.getInstance()
val year = calendar.get(Calendar.YEAR).toString()
val monthOfYear = (calendar.get(Calendar.MONTH) + 1).toString()
val dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH).toString()
val hour = calendar.get(Calendar.HOUR_OF_DAY).toString()
val minute = calendar.get(Calendar.MINUTE).toString()
val second = calendar.get(Calendar.SECOND).toString()
return "NewCsv$year-$monthOfYear-$dayOfMonth-$hour-$minute-$second.csv"
}
}
ActivityやFragmentからこのクラスとwriteCsv()を呼び出してCSVファイルを取得する想定です。
writeCsvの引数(data)やファイル名などはアプリに合わせて適宜変更してください。
DataForCsv.kt (CSVのカラム設定クラス)
// CSVファイルのカラム設定クラス
data class DataForCsv(
@CsvBindByPosition(position = 0, required = true)
val name : String = "",
@CsvBindByPosition(position = 1, required = false)
val birthDay : String? = "",
)
ここでCSVに挿入するカラムを設定します。
@CsvBindByPositionを利用することで、CSVファイルの列の順番(position)や必須項目(required)かを指定できます。
MainActivity.kt (CSVファイル作成実行・送信するアクティビティ)
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
sendCsv()
}
// CSVを生成して送信用ダイアログを表示させる
private fun sendCsv() {
// APIなどで取得したUserResponseリスト
val userList = arrayListOf<UserResponse>(
UserResponse("一郎", "1993/11/11"),
UserResponse("二郎", "1995/02/14"),
)
// CSVファイルを生成
val csv = OpenCsv().writeCsv(userList, this)
if (csv != null) {
// 生成したCSVファイルをメールやSNSなどに送信するダイアログを表示させる
val sharingIntent = Intent(Intent.ACTION_SEND)
// ここはアプリに合わせて変更してください
val uri = FileProvider.getUriForFile(
this, "com.example.csv_example_app.fileprovider", csv
)
sharingIntent.type = "text/plain"
sharingIntent.putExtra(Intent.EXTRA_STREAM, uri)
startActivity(
Intent.createChooser(
sharingIntent,
"CSVファイルを送信" // ダイアログのタイトル
)
)
}
}
}
Intent(Intent.ACTION_SEND)を利用し、startActivityを行うことでデータを送信するダイアログ(Android Sharesheet)を表示します。
生成したCSVをこのintentに乗せておくことで、CSVを共有できます。
UserResponse(CSVに乗せるデータクラス)
class UserResponse constructor(
var name : String? = "",
var birthDay : String? = ""
) : Parcelable {
constructor(parcel: Parcel) : this() {
name = parcel.readString()
birthDay = parcel.readString()
}
override fun writeToParcel(parcel: Parcel, p1: Int) {
parcel.let {
it.writeString(name)
it.writeString(birthDay)
}
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<UserResponse> {
override fun createFromParcel(parcel: Parcel): UserResponse {
return UserResponse(parcel)
}
override fun newArray(size: Int): Array<UserResponse?> {
return arrayOfNulls(size)
}
}
}
こちらは唯のデータクラスなので、適宜変更してください。
終わりに
アプリでCSVの生成をしなければならないことになって、かなり面倒そうなイメージを持っていましたが、便利なパッケージがあり簡単に実装できました。先人方には感謝しなければなりませんね。
コメント