スキップしてメイン コンテンツに移動

POIで行コピーを行う (Apache POI Tips)

Apache POIで、行のコピーを行う方法を紹介します。

残念なことに、Apache POIには行コピーのようなメソッドは用意されていません。
面倒ですが、行の内容を取得して、その中のセルの値およびスタイルをコピーするという方法しかないようです。

POIで行コピーを行う のイメージ

サンプルコード

さっそく、行のコピーを行うサンプルコードを、紹介したいと思います。

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.*;

/**
 * POIで行をコピーする処理
 * @param workbook ワークブック
 * @param worksheet ワークシート
 * @param sourceRowNum コピー元の行インデックス
 * @param destinationRowNum コピー先の行インデックス
 */
private static void copyRow(Workbook workbook, Sheet worksheet, int sourceRowNum, int destinationRowNum) {
  Row newRow = worksheet.getRow(destinationRowNum);
  Row sourceRow = worksheet.getRow(sourceRowNum);

  if (newRow != null) {
    //コピー先に行が既に存在する場合、1行下にずらす
    worksheet.shiftRows(destinationRowNum, worksheet.getLastRowNum(), 1);
    newRow = worksheet.createRow(destinationRowNum);
  } else {
    //存在しない場合は作成
    newRow = worksheet.createRow(destinationRowNum);
  }

  // セルの型、スタイル、値などをすべてコピーする
  for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
    Cell oldCell = sourceRow.getCell(i);
    Cell newCell = newRow.createCell(i);

    // コピー元の行が存在しない場合、処理を中断
    if (oldCell == null) {
      newCell = null;
      continue;
    }

    //スタイルのコピー
    CellStyle newCellStyle = workbook.createCellStyle();
    newCellStyle.cloneStyleFrom(oldCell.getCellStyle());
    newCell.setCellStyle(newCellStyle);

    //コメントのコピー
    if (oldCell.getCellComment() != null) {
      newCell.setCellComment(oldCell.getCellComment());
    }

    //ハイパーリンクのコピー
    if (oldCell.getHyperlink() != null) {
      newCell.setHyperlink(oldCell.getHyperlink());
    }

    //セル型のコピー
    newCell.setCellType(oldCell.getCellType());

    //セルの値をコピー
    switch (oldCell.getCellType()) {
    case Cell.CELL_TYPE_BLANK:
      newCell.setCellValue(oldCell.getStringCellValue());
      break;
    case Cell.CELL_TYPE_BOOLEAN:
      newCell.setCellValue(oldCell.getBooleanCellValue());
      break;
    case Cell.CELL_TYPE_ERROR:
      newCell.setCellErrorValue(oldCell.getErrorCellValue());
      break;
    case Cell.CELL_TYPE_FORMULA:
      newCell.setCellFormula(oldCell.getCellFormula());
      break;
    case Cell.CELL_TYPE_NUMERIC:
      newCell.setCellValue(oldCell.getNumericCellValue());
      break;
    case Cell.CELL_TYPE_STRING:
      newCell.setCellValue(oldCell.getRichStringCellValue());
      break;
    }
  }

  //セル結合のコピー
  for (int i = 0; i < worksheet.getNumMergedRegions(); i++) {
    CellRangeAddress cellRangeAddress = worksheet.getMergedRegion(i);
    if (cellRangeAddress.getFirstRow() == sourceRow.getRowNum()) {
      CellRangeAddress newCellRangeAddress = new CellRangeAddress(newRow.getRowNum(),
          (newRow.getRowNum() + (cellRangeAddress.getLastRow() - cellRangeAddress.getFirstRow())),
          cellRangeAddress.getFirstColumn(), cellRangeAddress.getLastColumn());
      worksheet.addMergedRegion(newCellRangeAddress);
    }
  }
}

コピーする内容

上のサンプルコードを見てもらえれば、分かると思いますが、今回紹介した行のコピーを行うサンプルコードでは、元の行から以下の内容をコピーする処理になっています。

コピーする内容
文字色・背景色などのセルスタイル
コメント
ハイパーリンク
セル型
セルの値
セル結合

コピー先の行に、既に値がある場合

以下の表のように、コピー先に既に行が存在する場合、今回紹介したサンプルコードでは、既に存在するコ行を1行ずらしてから、行のコピーを行っています。

[コピー前]

No 名称
1 りんご ← コピー元
2 みかん
3 もも ← コピー先

[コピー後]

No 名称
1 りんご
2 みかん
1 りんご
3 もも

ちなみに、この1行ずらす処理はサンプルコード17行目付近の、以下の部分で行っています。

    worksheet.shiftRows(destinationRowNum, worksheet.getLastRowNum(), 1);

まとめ

いかがでしょうか。
今回紹介したサンプルコードを、共通関数として保存しておけば、今後は共通関数を一発呼ぶだけになり、行のコピーが楽になるかと思います。

参考URL

みんな大好き stack overflow
https://stackoverflow.com/questions/5785724/how-to-insert-a-row-between-two-rows-in-an-existing-excel-with-hssf-apache-poi

※上記URLに掲載されているプログラムだと、うまく動かなかったので、本記事で紹介しているサンプルコードは一部修正しています。

コメント

このブログの人気の投稿

axiosの使い方まとめ (GET/POST/例外処理)

axiosの使い方まとめ (GET/POST/例外処理)最近何かとよく使うJavaScriptでAJAX通信を行うaxiosについて、簡単に使い方をまとめました。GETリクエストをaxiosで送るまずはGETリクエストをaxiosで送る方法です。const res =await axios.get('/users') console.log(res.data)分割代入の記法を使うと、以下のようにも書けますconst{data}=await axios.get('/users') console.log(data)クエリパラメータ (URLパラメータ)を指定クエリパラメータを指定する方法は2つあります。1つ目は、axios.getに指定するURLに直接記述する方法です。axios.get('/user?id=123')2つめは、axios.getの第2引数に、オプション指定する方法です。axios.get('/user',{ params:{ id:123}})POSTリクエストをaxiosで送る次はPOSTリクエストをaxiosで送る方法です。JSON形式でPOSTするJSON形式でPOSTする場合は、axios.postの第2引数に、送信するデータをJavaScriptオブジェクトで指定します。const res =await axios.post('/user',{ id:123, name:'Yamada Tarou'})application/x-www-form-urlencoded形式でPOSTするapplication/x-www-form-urlencoded形式でPOSTする場合は、URLSearchParamsを使います。var params =newURLSearchParams() params.append('id',123) params.append('name','Yamada Tarou')const res =await axios.post('/user', params)スポンサーリンク axios でファイルをアップロードする画像などのファイルを、…

[VB, C#] Windows 8, Window 10 で ImeModeが制御できない問題を解決する

[VB, C#] Windows 8, Window 10 で ImeModeが制御できない問題を解決するタイトルの通りですが、Windows 8 以降では Windows Form アプリケーションで、コントロールの ImeMode に Katakana や KatakanaHalf を設定しても、カタカナになってくれません。なぜ ImeMode が効かないのか?Windows 8 以降、IME Mode の切り替えは、ユーザー単位で切り替わるようになった為、アプリから IME Mode 制御が出来ないようになりました。
(IME をON にした場合、常に ひらがな モードになます)※ Windows 7までは、IME Modeの切り替えはアプリ単位で行われていた為、問題なくアプリから IME制御が行えました。スポンサーリンク 対処方法Windows 8 以降、IMEの制御は、InputScope クラスの利用が推奨されています。
しかし、InputScope クラスは、WPF、Windows ストアアプリでしか使えない為、Windows Formアプリでは使用できません。
(Windows Form はもう使うな!という事でしょうか (涙) )結論としては、コントールパネルの設定で、IMEの制御をユーザ単位から アプリ単位に変更する事ができます。
これで、Windows Formアプリでも 従来通りIMEの制御を行う事が出来ます。おわりにこの方法だと、アプリをインストールする端末すべてに設定が必要となり、とっても面倒です。。。
しかし、今の所これしか方法がない状態です。
これからは Windows Formではなく、WPFや Windows ストアアプリで作れという事ですかね (^^;)

MailKitの使い方! エンコーディング指定や添付ファイをメールで送信する方法[C#/VB Tips]

MailKitの使い方! エンコーディング指定や添付ファイをメールで送信する方法[C#/VB Tips]MailKitを使ってメールを送るサンプルコードです。(C#)UTF8/iso-2022-jpのエンコーディング指定、GMail/YahooのSMTPサーバで送るなど、4つのサンプルコードでMailKitの使い方を紹介します。MailKitって何?2017年に.NET標準のSystem.Net.Mail.SmtpClientが廃止予定となり、Microsoftより今後はオープンソースライブラリである、MailKitに置き換えるとアナウンスがありました。既にSmtpClientは非推奨になっており、今後は廃止されていきます。現在、SmtpClientを使用したソースコードには、Visual StudioからMailKitを使うよう警告が出るようになっています。さっそく、MailKitを使ってメールを送信するサンプルコードを作っていきます。UTF8でメールを送信文字エンコーディングを、UTF8でメールを送信するサンプルコードです。
MailKitは、デフォルトの文字エンコーディングがUTF8なっている為、シンプルなコードでメールを送信する事ができます。var host ="<smtp server name>"; var port =25;// or 587using(var smtp =new MailKit.Net.Smtp.SmtpClient()){//SMTPサーバに接続する smtp.Connect(host, port, MailKit.Security.SecureSocketOptions.Auto);//認証が必要な場合は、以下のコメントを解除//smtp.Authenticate("<id>", "<password>");//送信するメールを作成する var mail =new MimeKit.MimeMessage(); var builder =new MimeKit.BodyBuilder(); mail.From.Add(new MimeKit.MailboxAddress("",&quo…