Ticker

6/random/ticker-posts

Apache POI ile Java'da Excel Dosya Yazma ve Okuma

Microsoft Office dosyalarını Java'da okumak ve düzenlemek için geliştirilen Apache POI kütüphanesi ile metin, sayısal, tarih ve resim türünde verilerin nasıl xlsx uzantılı excel dosyasına yazılacağını ve okunacağını göreceğiz.


Apache POI Excel okuma Yazma
Apache POI Excel okuma Yazma

Bu yazıyı yazarken son sürüm 5.0.0 idi ve şu adresten maven bağımlılığını projemize ekleyerek çalışmaya başlayabiliriz.

Bir ürün envanteri excel dosyası oluşturup daha sonra okuyacağız. Bunun için öncelikle aşağıdaki gibi Product.java isimli bir sınıf oluşturalım. Parasal değerler için BigDecimal kullanmak double gibi küsüratı kararsız bir yapı kullanmaktan daha iyidir.

import java.math.BigDecimal;
import java.util.Date;

public class Product {

	private int id;
	
	private String barcode;
	
	private String name;
	
	private String description;
	
	private BigDecimal price;
	
	private int stock;
	
	private double remainingStockPercentage;
	
	private Date purchaseDate;
	
	private byte[] image;

  // getters & setters
}

.xlsx uzantılı excel dosyası yazmak için WriteInventoryExcel.java isimli bir sınıf oluşturalım ve main metoduna aşağıdaki kodları ekleyelim. 

Apache poi ile workbook nesnesi oluşturalım ve "Products" isimli bir sekme (sheet) oluşturalım.

XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("Products");

 Resim dosyalarını excel dosyasına yazmak için Drawing nesnesi oluşturalım.

CreationHelper creationHelper = workbook.getCreationHelper();
Drawing drawing = sheet.createDrawingPatriarch();

 Örnek olması için 2 adet Product nesnesi oluşturalım ve içeriğini dolduralım.

Product deneyapKart = new Product();

deneyapKart.setId(1);
deneyapKart.setBarcode("111222333445566");
deneyapKart.setName("Deneyap Kart");
deneyapKart.setDescription(
		"Ülkemizin mühendislik kaynakları kullanılarak geliştirilen Deneyap Kart; güçlü işlemcisi,"
				+ " dayanıklı tasarımı ve çok yönlü giriş/çıkış pinleri ile Elektronik Programlama,"
				+ " Nesnelerin İnterneti (IoT) ve Yapay Zeka alanlarında başlangıç için ideal bir karttır.");
deneyapKart.setPrice(new BigDecimal("139.99"));
deneyapKart.setPurchaseDate(new Date());
deneyapKart.setRemainingStockPercentage(0.85);
deneyapKart.setStock(1581);

// read image

FileInputStream stream =
		new FileInputStream( "Dene_yap_089.jpg" );

byte[] image = IOUtils.toByteArray(stream);

deneyapKart.setImage(image);

Product xiaomiRedmi = new Product();

xiaomiRedmi.setId(2);
xiaomiRedmi.setName("Xiaomi Redmi Note 10 64GB (Xiaomi Türkiye Garantili)");
xiaomiRedmi.setDescription("Xiaomi Redmi Note 10 64GB, Android işletim sistemli telefonlar arasında "
		+ "kendine ayrı bir yer buluyor."
		+ " Çerçevesiz formdaki ürün, ağırlığının azalması ve konforlu kullanım için özel"
		+ " polikarbon materyal kasasıyla geliyor. Xiaomi Redmi Note 10 64GB "
		+ "işletim sistemi olarak Android 11 ile gelirken arayüzü ise"
		+ " Xiaomi imzası taşıyan MIUI 12 olarak sahiplerinin karşısına çıkıyor.");

xiaomiRedmi.setBarcode("HBCV0000027FN6");

xiaomiRedmi.setPrice(new BigDecimal("2849.90"));
xiaomiRedmi.setPurchaseDate(new Date());
xiaomiRedmi.setStock(251);
xiaomiRedmi.setRemainingStockPercentage(0.53);

stream = new FileInputStream( "xiaomi-redmi-note-10-64-gb-z.jpg" );

byte[] xiaomiImage = IOUtils.toByteArray(stream);

xiaomiRedmi.setImage(xiaomiImage);

Kodda görüldüğü gibi resim dosyalarını byte array olarak okuduğumuzu not edelim.

Apache POI ile Hücrelere Stil (Style) Uygulama

Excel dosyamızda ilk satırı başlık satırı olarak kullanacağız. Kolonların başlıklarını kalın stilde (bold) ekleyeceğiz. Bu sayede hücrelere stil (style) uygulamayı da görmüş olacağız.

int rowCount = 0;

XSSFRow titleRow = sheet.createRow(rowCount++);

int columnCount = 0;

CellStyle boldStyle = workbook.createCellStyle();
Font font = workbook.createFont();
font.setBold(true);
boldStyle.setFont(font);

XSSFCell cell1 = titleRow.createCell(columnCount++);
cell1.setCellValue("ID");
cell1.setCellStyle(boldStyle);


XSSFCell cell2 = titleRow.createCell(columnCount++);
cell2.setCellValue("Ürün Adı");
cell2.setCellStyle(boldStyle);

XSSFCell cell3 = titleRow.createCell(columnCount++);
cell3.setCellValue("Açıklama");
cell3.setCellStyle(boldStyle);

XSSFCell cell4 = titleRow.createCell(columnCount++);
cell4.setCellValue("Barkod");
cell4.setCellStyle(boldStyle);

XSSFCell cell5 = titleRow.createCell(columnCount++);
cell5.setCellValue("Fiyat");
cell5.setCellStyle(boldStyle);

XSSFCell cell6 = titleRow.createCell(columnCount++);
cell6.setCellValue("Tarih");
cell6.setCellStyle(boldStyle);

XSSFCell cell7 = titleRow.createCell(columnCount++);
cell7.setCellValue("Stok");
cell7.setCellStyle(boldStyle);

XSSFCell cell8 = titleRow.createCell(columnCount++);
cell8.setCellValue("Kalan Stok Yüzdesi");
cell8.setCellStyle(boldStyle);

XSSFCell cell9 = titleRow.createCell(columnCount++);
cell9.setCellValue("Resim");
cell9.setCellStyle(boldStyle);

Apache POI ile Excel Dosyasına Resim Dosyası Ekleme

Şimdi de örnek olarak oluşturduğumuz Deneyapkart nesnesini excel ürün envanteri dosyamıza bir satır olarak ekleyelim. Tarih verisini SimpleDateFormat ile formatlanmış bir String'e çevirip metin olarak kaydediyoruz. Düz Date nesnesi olarak da yazılabilirdik fakat o zaman long türünde timestamp değerini yazdıracaktı ve dosyayı açtığımızda uzun bir sayı görecek ve tarih değeri olduğu anlaşılmayacaktı.

XSSFRow row1 = sheet.createRow(rowCount++);

columnCount = 0;

cell1 = row1.createCell(columnCount++);
cell1.setCellValue(deneyapKart.getId());

cell2 = row1.createCell(columnCount++);
cell2.setCellValue(deneyapKart.getName());

cell3 = row1.createCell(columnCount++);
cell3.setCellValue(deneyapKart.getDescription());

cell4 = row1.createCell(columnCount++);
cell4.setCellValue(deneyapKart.getBarcode());

cell5 = row1.createCell(columnCount++);
cell5.setCellValue(deneyapKart.getPrice().doubleValue());


SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");

cell6 = row1.createCell(columnCount++);
cell6.setCellValue(dateFormat.format(deneyapKart.getPurchaseDate()));

cell7 = row1.createCell(columnCount++);
cell7.setCellValue(deneyapKart.getStock());

cell8 = row1.createCell(columnCount++);
cell8.setCellValue(deneyapKart.getRemainingStockPercentage());


ClientAnchor anchor = creationHelper.createClientAnchor();
anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE );

int pictureIndex =
		workbook.addPicture(deneyapKart.getImage(), Workbook.PICTURE_TYPE_JPEG);

anchor.setCol1(columnCount++);
anchor.setRow1( 1 ); 
anchor.setRow2( 2 );
anchor.setCol2(columnCount++);
Picture pict = drawing.createPicture( anchor, pictureIndex );
pict.resize();

Resim dosyasını yazmak için ClientAnchor nesnesini kullanarak ve drawing nesnesi ile Picture nesnesi

oluşturduğumuzu not edelim.

Benzer şekilde xiaomiRedmi nesnesini de 2. satır olarak yazdıralım.

XSSFRow row2 = sheet.createRow(rowCount++);

columnCount = 0;


cell1 = row2.createCell(columnCount++);
cell1.setCellValue(xiaomiRedmi.getId());

cell2 = row2.createCell(columnCount++);
cell2.setCellValue(xiaomiRedmi.getName());

cell3 = row2.createCell(columnCount++);
cell3.setCellValue(xiaomiRedmi.getDescription());

cell4 = row2.createCell(columnCount++);
cell4.setCellValue(xiaomiRedmi.getBarcode());

cell5 = row2.createCell(columnCount++);
cell5.setCellValue(xiaomiRedmi.getPrice().doubleValue());

cell6 = row2.createCell(columnCount++);
cell6.setCellValue(dateFormat.format(xiaomiRedmi.getPurchaseDate()));

cell7 = row2.createCell(columnCount++);
cell7.setCellValue(xiaomiRedmi.getStock());

cell8 = row2.createCell(columnCount++);
cell8.setCellValue(xiaomiRedmi.getRemainingStockPercentage());


anchor = creationHelper.createClientAnchor();
anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE );

stream = new FileInputStream( "xiaomi-redmi-note-10-64-gb-z.jpg" );

pictureIndex = workbook.addPicture(xiaomiRedmi.getImage(), Workbook.PICTURE_TYPE_JPEG);

anchor.setCol1(columnCount++);
anchor.setRow1( 2 );
anchor.setRow2( 3 );
anchor.setCol2(columnCount++);
pict = drawing.createPicture( anchor, pictureIndex );
pict.resize();

Ekleyeceğimiz satırlar tamamlandığında son adım olarak oluşturduğumuz workbook nesnesini inventory.xlsx isimli bir excel dosyasına yazdıralım.

try (FileOutputStream outputStream = new FileOutputStream("inventory.xlsx")) {
	workbook.write(outputStream);
}

Şimdi WriteInventoryExcel.java sınıfını çalıştıralım. Sonuç olarak içeriği aşağıdaki gibi olan inventory.xlsx isimli bir dosya oluşacaktır.

inventory.xlsx

Apache POI ile xlsx Uzantılı Excel Dosyası Okuma

Şimdi de yazmış olduğumuz inventory.xlsx dosyasını Apache POI kütüphanesi ile okuyalım.

ReadInventoryExcel.java isimli bir sınıf oluşturalım ve main metoduna aşağıdaki kodları ekleyelim.

Workbook workbook = WorkbookFactory.create(new File("inventory.xlsx"));

Iterator<Sheet> sheetIterator = workbook.sheetIterator();

Sheet productSheet = sheetIterator.next();

System.out.println("sheet name: " + productSheet.getSheetName());

Iterator<Row> rowIterator = productSheet.rowIterator();

while (rowIterator.hasNext()) {
	
	Row row = rowIterator.next();
	
	if(row.getRowNum() == 0) {
		// baslik satirini atla
		continue;
	}
	
	Cell cell1 = row.getCell(0);
	
	Integer id = Integer.valueOf((int) cell1.getNumericCellValue());
	
	System.out.println("id: " + id);
	
	Cell cell2 = row.getCell(1);
	
	String name = cell2.getStringCellValue();
	
	System.out.println("name: " + name);
	
	Cell cell3 = row.getCell(2);
	
	String description = cell3.getStringCellValue();
	
	System.out.println("description: " + description);
	
	Cell cell4 = row.getCell(3);
	
	String barcode = cell4.getStringCellValue();
	
	System.out.println("barcode: " + barcode);

	Cell cell5 = row.getCell(4);
	
	BigDecimal price = new BigDecimal(cell5.getNumericCellValue());
	price = price.setScale(2, BigDecimal.ROUND_HALF_UP);
	
	System.out.println("price: " + price);
	
	SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
	
	Cell cell6 = row.getCell(5);
	
	String dateString = cell6.getStringCellValue();
	
	Date purchaseDate = dateFormat.parse(dateString);
	
	System.out.println("purchase date: " + purchaseDate);
	
	Cell cell7 = row.getCell(6);
	
	Integer stock = Integer.valueOf((int) cell7.getNumericCellValue());
	
	System.out.println("stock: " + stock);
	
	
	Cell cell8 = row.getCell(7);
	
	double remainingStockPercantage = cell8.getNumericCellValue();
	
	System.out.println("remaining stock percantage: " + remainingStockPercantage);
	
	System.out.println();
	
}

Date bilgisini yazdığımız formatın aynısı ile okuyup parse ediyoruz. Parasal fiyat bilgisini de BigDecimal'a çevirip noktadan sonraki sadece 2 basamağı kullanmasını istiyoruz.

Apache POI ile Excel Dosyasından Resim Okuma

Bir önceki bölümde dosyaya eklediğimi JPG türündeki dosyaları okuyup yine dosyaya farklı isimlerde yazdıralım.

List allPictures = workbook.getAllPictures();
int i = 1;
for (Iterator it = allPictures.iterator(); it.hasNext(); ) {
	PictureData picture = (PictureData)it.next();
	String extension = picture.suggestFileExtension();
	byte[] data = picture.getData();
	if (extension.equals("jpeg")){
	  FileOutputStream out = new FileOutputStream(i++ + "_picture.jpg");
	  out.write(data);
	  out.close();
	}
}

Oluşturduğumuz bu ReadInventoryExcel.java sınıfını çalıştırdığımızda konsolda satır bilgilerini göreceğiz ve 1_picture.jpg ve2_picture.jpg isimli dosyaların oluştuğunu göreceğiz.

Yorum Gönder

0 Yorumlar