非IT企業に勤める中年サラリーマンのIT日記

非IT企業でしかもITとは全く関係ない部署にいる中年エンジニア。唯一の趣味がプログラミングという”自称”プログラマー。

JavaFXでcsvファイルを読み込んでTableViewに表示する方法

   

JavaFXでcsvファイルを読み込んでTableView上に表示させる方法です。任意のcsvファイルなので列数があらかじめわかりません。JavaFXのTableViewで列を動的に生成する方法は以前書きました。これをベースに作りました。

広告

まずはプログラムの動きから

起動するとこんな外観です。左上に「Open」ボタンがありますが、これを押すとcsvファイルを選べます。

 

「Open」ボタンを押すとFileChooerが現れてcsvファイルを指定できます。

 

開くと以下の通りTableViewにデータがセットされます。csvファイルの先頭行がTableViewのヘッダーになります。

 

1つ注意点として、1行目の項目がないと、その下のデータは無視されます。例えば下図のように4行目の5列目に「35」というデータが存在しても、項目がない(赤枠)ので、TableViewには表示されません。

 

以下のように項目をちゃんと記載すれば(以下の例では「E」)、ちゃんとTableViewに現れます。

 

ソースコード全文

ソースコード全文です。コピペしてコンパイルしてください。

まずはFXMLファイル(CsvTable.fxml)

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.ToolBar?>
<?import javafx.scene.layout.VBox?>

<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/9" xmlns:fx="http://javafx.com/fxml/1" fx:controller="CsvTable">
  <children>
    <ToolBar prefHeight="40.0" prefWidth="200.0">
      <items>
        <Button mnemonicParsing="false" onAction="#btnAction" text="Open" />
      </items>
    </ToolBar>
    <TableView fx:id="table" prefHeight="403.0" prefWidth="600.0" />
  </children>
</VBox>
  

 

データクラス(CsvData.java)

import java.util.*;
import javafx.beans.property.*;

public class CsvData {
  private ArrayList&lt;String&gt; list;

  public CsvData(ArrayList&lt;String&gt; list) {
    this.list = list;
  }

  public void add(String data){ list.add(data); }
  public StringProperty get(int index){
    return new SimpleStringProperty(list.get(index));
  }
}
 

 

本体です。(CsvTable.java)

import javafx.application.Application;
import javafx.fxml.*;
import javafx.scene.*;
import javafx.stage.*;
import javafx.scene.layout.*;
import javafx.event.ActionEvent;
import javafx.scene.control.*;
import javafx.collections.*;
import javafx.scene.control.cell.*;
import javafx.scene.control.TableColumn.*;
import java.util.*;
import javafx.util.*;
import javafx.beans.value.*;
import javafx.beans.property.*;
import java.io.*;

public class CsvTable extends Application {
  @FXML private TableView table;
  private List&lt;TableColumn&gt; columnList;
  private ObservableList&lt;CsvData&gt; data;

  public static void main(String[] args) {
    launch(args);
  }

  @Override
  public void start(Stage stage) throws Exception{
    VBox root = FXMLLoader.load(getClass().getResource("CsvTable.fxml"));
    stage.setTitle("csv file");
    stage.setScene(new Scene(root));
    stage.show();
  }

  @FXML
  public void btnAction(ActionEvent e) {
    FileChooser fc = new FileChooser();
    fc.setTitle("ファイル選択");
    fc.getExtensionFilters().addAll(
      new FileChooser.ExtensionFilter("CSVファイル", "*.csv", "*.CSV"),
      new FileChooser.ExtensionFilter("すべてのファイル", "*.*")
    );
    File file = fc.showOpenDialog(null);
    if(file == null) return;
    //csvファイル読み込み
    try {
      columnList = new ArrayList&lt;TableColumn&gt;();
      File f = new File(file.getPath());
      BufferedReader br = new BufferedReader(new FileReader(f));
      String line;
      int cnt=0;
      int len = 0;
      while ((line = br.readLine()) != null) {
        String[] d = line.split(",", 0); // 行をカンマ区切りで配列に変換
        if(cnt==0){
          //先頭行(項目行)の処置
          ArrayList&lt;TableColumn&gt; dataCols = new ArrayList&lt;TableColumn&gt;();
          len = d.length; //項目列数を保持しておく
          for (int i=0; i&lt;d.length; i++) {
            if(d[i]==null) d[i]="";
            dataCols.add(new TableColumn(d[i]));
            columnList.add(dataCols.get(i));
            final int index = i;
            dataCols.get(i).setCellValueFactory(new Callback&lt;CellDataFeatures&lt;CsvData, String&gt;, ObservableValue&lt;String&gt;&gt;() {
              public ObservableValue&lt;String&gt; call(CellDataFeatures&lt;CsvData, String&gt; p) {
                return p.getValue().get(index);
              }
            });
          }
          table.getColumns().addAll(columnList);
          data = FXCollections.observableArrayList();
          table.itemsProperty().setValue(data);
          table.setItems(data);
        }else{
          //2行目以降(データ行)
          ArrayList&lt;String&gt; col = new ArrayList&lt;String&gt;();
          //項目列数分だけループ
          for(int i=0; i&lt;len; i++){
            if(d.length &gt; i){
              if(d[i]==null) d[i]="";
              col.add(d[i]);
            }else{ //もしデータ数が少なかったら空欄を入れておく
              col.add("");
            }
          }
          data.addAll( new CsvData(col) );
        }
        cnt++;
      }
      br.close();
    }catch (IOException ie){
      System.out.println(ie);
    }catch (Exception ie){
      System.out.println(ie);
    }
  }
}
 

 

広告

 - Java