スポンサーリンク

【Android Kotlin 】OpenCsvでCSVファイルを作成してSNSやメールに送信する

Kotlin

当ブログは福岡を中心とした都市の再開発や都市政策の紹介、考察を行うことをメインとしていますが、今回の記事では、本業であるアプリ・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を共有できます。

Sharesheet 画面下からぬるっと出てきます。

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の生成をしなければならないことになって、かなり面倒そうなイメージを持っていましたが、便利なパッケージがあり簡単に実装できました。先人方には感謝しなければなりませんね。

コメント

タイトルとURLをコピーしました