[JAVA] Excel mit Formeln mit XlsMapper ausgeben

Auslösen

"Ich möchte Excel in Java ausgeben, aber ich möchte es nicht durch eine Zellennummer wie Apache POI angeben", "Ich möchte eine Bibliothek auf etwas höherer Ebene", ich habe eine Bibliothek namens XlsMapper gefunden, also habe ich es versucht Es war. Bitte weisen Sie auf Fehler oder Implementierungshinweise hin.

Was ist XlsMapper?

Eine Java-Bibliothek, die Excel Java zuordnet. Früher gab es eine berühmte Java-Bibliothek namens XLSBeans, die zu einem Buch verarbeitet wurde, aber ihre Entwicklung scheint gestoppt zu sein. Basierend auf dieser Version 1.1 scheinen Einzelpersonen nach und nach Funktionen als weiteres Projekt XlsMapper hinzuzufügen. (Eigentlich habe ich eine Weile XLS Beans verwendet.)

Was ist bequemer als POI?

Wenn Sie über POI auf Excel zugreifen, wird für die Liste aus der Datenbank (wenn Sie die Informationen kennen) Aufzeichnung 1. Setzen und formatieren Sie Element 1 in der Zelle in der M-ten Spalte des N-ten Datensatzes in Excel. Aufzeichnung 1. Setzen und formatieren Sie Element 2 auf die Zelle in der Spalte M + 1. des N-ten Excel-Datensatzes. : Aufzeichnung 2. Setzen und formatieren Sie Element 1 in der Zelle in der M-ten Spalte von N + 1. Datensatz in Excel. :

Wenn Sie einen solchen Zugriff implementieren müssen oder wenn sich die Spaltenstruktur ändert, müssen Sie die N- und M-Werte entsprechend verschieben. Mit dieser Bibliothek können Sie Excel-Werte POJOs zuordnen und die zugeordneten POJOs wie einem OR-Mapper in Excel schreiben, wodurch unnötige Verarbeitungsbeschreibungen reduziert werden. Darüber hinaus müssen Sie sich nicht die Mühe machen, das Format usw. zu implementieren, da Einstellungen wie das Kopieren des vorherigen Datensatzes mit Anmerkungen vorgenommen werden können.

Offizielle Website

Versuchte Umgebung

Implementierung

Maven Fügen Sie pom Folgendes hinzu. * Ausgelassen, außer für Excel-bezogene Elemente.

pom.xml


<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi</artifactId>
	<version>4.0.1</version>
</dependency>
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-ooxml</artifactId>
	<version>4.0.1</version>
</dependency>
<dependency>
	<groupId>com.github.mygreen</groupId>
	<artifactId>xlsmapper</artifactId>
	<version>2.0</version>
</dependency>

Briefpapierdatei

Bereiten Sie ein Buch mit der folgenden Tabelle vor. Es geht darum, die Tabelle mit einer Linie zu versehen.

無題.png

SpringBootApplication

DemoService.java


@SpringBootApplication
public class DemoApplication {

	public static void main(String[] args) {
		//Geben Sie das Argument einfach als Map zurück
		CommandLineParamsMap params = new CommandLineParamsMap(args);
		try (ConfigurableApplicationContext ctx = SpringApplication.run(DemoApplication.class, args)) {
			DemoService app = ctx.getBean(DemoService.class);
			app.execute(params);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

Service

DemoService.java


@Service
@Slf4j
public class DemoService {
	private static final String TEMPLATE_FILE_PATH = "template\\Benutzerliste_%s Jahr%s Monat%s Tagesschöpfung.xlsx";
	private static final String OUTPUT_FILE_PATH = "C:\\test\\Benutzerliste_%s Jahr%s Monat%s Tagesschöpfung.xlsx";

	public String execute(CommandLineParamsMap params) {
		log.info("DemoService START");
		LocalDate outPutDate = getOutPutDate(params.getValue("date"));
		log.info("date:" + outPutDate);

		String outputPath = makeTargetPath(outPutDate);

		//Tabellendaten abrufen
		List<UsingListRecord> target = getData();

		//Stellen Sie jede Information in Blatt ein
		UsingListSheet sheet = new UsingListSheet();
		sheet.setOutPutDate("Ausgabedatum:" + outPutDate);
		sheet.setRecords(target);
		//Fügen Sie der letzten Zeile die gesamte Zeile der Formel hinzu
		sheet.addSummaryRecord();

		XlsMapper xlsMapper = new XlsMapper();
		try {
			//Schreiben Sie dies (keine Schleife erforderlich)!
			xlsMapper.save(
					new FileInputStream(TEMPLATE_FILE_PATH), //Excel-Datei der Vorlage
					new FileOutputStream(outputPath), //Excel-Datei zum Schreiben
					sheet //Daten erstellt
			);
		} catch (XlsMapperException | IOException e) {
			throw new RuntimeException(e);
		}

		//Lesen Sie die geschriebene Tabelle und versuchen Sie, sie auszugeben
		List<UsingListRecord> records = read(outputPath);
		records.forEach(r->log.info(r.toString()));

		log.info("DemoService END");
		return "###########success###########";
	}

	/**
	 *yyyymmdd → LocalDate-Objekt
	 * @param value
	 * @return
	 */
	private LocalDate getOutPutDate(String value) {
		int year = Integer.parseInt(value.substring(0, 4));
		int month = Integer.parseInt(value.substring(4, 6));
		int day = Integer.parseInt(value.substring(6, 8));
		return LocalDate.of(year, month, day);
	}

	//Datenerfassung
	private List<UsingListRecord> getData() {
		//Eigentlich bringen Sie es aus der DB
		List<UsingListRecord> list = new ArrayList<>();
		list.add(getSample("Anakin Skywalker", "Tatween", "Mensch", 100, "Asoka Tano", 1));
		list.add(getSample("Padme Amidara", "Naboo", "Mensch", 100, null, 2));
		list.add(getSample("Luke Skywalker", "Polizei Masa", "Mensch", 100, "Kairo Ren", 3));
		list.add(getSample("Kairo Ren", "Chandrila", "Mensch", 100, null, 4));
		list.add(getSample("Asoka Tano", "Siri", "Togruta", 100, null, 5));
		list.add(getSample("Darth Mall", "Dasomia", "Zabrak", null, "Wilde Opres", 6));
		list.add(getSample("Yoda", null, "Yodaの種族", 800, "Luke Skywalker", 7));
		return list;
	}

	//Gibt einen geeigneten Beispieldatensatz zurück
	private UsingListRecord getSample(String name, String homeTown, String species, Integer ageAvg, String apprentice,
			int i) {
		LocalDate d1 = LocalDate.of(2019, 3, 1).plusDays(i);
		Date startDate = Date.from(d1.atStartOfDay(ZoneId.systemDefault()).toInstant());

		UsingListRecord record = new UsingListRecord();
		record.setUserName(name);
		record.setPrice(new BigDecimal(120000 + i));
		record.setTax(0.08d + i);
		record.setUsingStartDate(startDate);
		record.setHomeTown(homeTown);
		record.setSpecies(species);
		record.setAgeAvg(ageAvg);
		record.setApprentice(apprentice);
		return record;
	}

	private List<UsingListRecord> read(String targetPath) {
		XlsMapper xlsMapper = new XlsMapper();
		UsingListSheet sheet = null;
		try {
			sheet = xlsMapper.load(
					new FileInputStream(targetPath), //Excel-Datei zu lesen
					UsingListSheet.class //Kommentierte Klasse.
			);
		} catch (XlsMapperException | IOException e) {
			throw new RuntimeException(e);
		}

		return sheet.getRecords();
	}

	private String makeTargetPath(LocalDate batchDate) {
		return String.format(OUTPUT_FILE_PATH, 
				batchDate.getYear(),
				batchDate.getMonthValue(),
				batchDate.getDayOfMonth()
				);
	}
}

Sheet Eine Klasse, die ein Blatt darstellt. Geben Sie @XlsSheet (name = "sheet name") an.

UsingListSheet.java


@Slf4j
@Data
@XlsSheet(name = "Benutzerliste")
public class UsingListSheet {

	private String outPutDate;

	@XlsHorizontalRecords(tableLabel = "Benutzerliste", bottom = 3)
	@XlsRecordOption(overOperation = OverOperation.Copy)
	private List<UsingListRecord> records;

	public void addSummaryRecord() {
		if (records == null) {
			this.records = new ArrayList<>();
		}

		UsingListRecord record = new UsingListRecord();
		//Übergeben Sie Ihre eigene Instanz
		record.setParent(this);

		record.setUserName("gesamt");
		records.add(record);
	}

	/**
	 *Versuchen Sie nach dem Schreiben der Tabelle, das Ausgabedatum mit POI festzulegen.
	 * @param sheet
	 */
	@XlsPostSave
	public void aa(final Sheet sheet) {
		Cell cell = POIUtils.getCell(sheet, 7, 0);
		CellStyle style=cell.getCellStyle();
		cell.setCellValue(outPutDate);
		cell.setCellStyle(style);
	}
}

@XlsHorizontalRecords Stellen Sie einen Tabellentyp mit einer Überschrift oben ein, z. B. das unten angehängte Excel. Geben Sie den Titel der Tabelle mit tableLabel an. Der untere Bereich gibt an, wie weit die tatsächliche Tabelle vom tableLabel entfernt ist. Wenn sich direkt unter tableLabel eine Tabellenüberschrift befindet, muss diese nicht angegeben werden.

@XlsRecordOption(overOperation = OverOperation.Copy) Geben Sie an, was zu tun ist, wenn mehr Datenzeilen vorhanden sind als in der Vorlage angegeben (durch den Rand festgelegt). Im Fall von OverOperation.Copy wird das Format der Zeile eine Ebene darüber kopiert und eine Zeile hinzugefügt. OverOperation.Insert beschädigt die Arbeitsmappe. (Siehe die Umgebung, die ich oben aus dem Grund ausprobiert habe.)

@XlsPostSave Die Methode dazu wird nach dem Schreiben der Datei automatisch ausgeführt. Es kann auch der Methode der Record-Klasse zugewiesen werden. Die Reihenfolge lautet @XlsPostSave of Sheet → @XlsPostSave of Record. Es gibt viele andere Dinge wie @XlsPreSave, siehe unten. 7. Verwalten von Lebenszyklusereignissen

Record Eine Klasse, die einen Datensatz der Tabelle darstellt, die in der Excel-Tabelle platziert werden soll.

UsingListRecord.java


@Data
public class UsingListRecord {
	//Zugeordnete Standortinformationen
	private Map<String, CellPosition> positions;
	//Übergeordnete Bean-Informationen
	private UsingListSheet parent;

	@XlsColumn(columnName = "Nutzer")
	private String userName;
	@XlsColumn(columnName = "Gebühr")
	@XlsFormula(methodName = "getSumFormula", primary = false)
	private BigDecimal price;
	@XlsColumn(columnName = "Umsatzsteuersatz")
	private Double tax;
	@XlsColumn(columnName = "Startdatum der Nutzung")
	@XlsDateTimeConverter(excelPattern = "yyyy/m/d")
	private Date usingStartDate;
	@XlsColumn(columnName = "Geburtsort")
	@XlsDefaultValue(value="--", cases=ProcessCase.Save)
	private String homeTown;
	@XlsColumn(columnName = "Rennen")
	private String species;
	@XlsColumn(columnName = "Durchschnittliches Leben")
	private Integer ageAvg;
	@XlsColumn(columnName = "Schüler")
	@XlsDefaultValue(value="--", cases=ProcessCase.Save)
	private String apprentice;

	//Stellen Sie die Gesamtformel zusammen
	public String getSumFormula(Point point) {

		//Ausgabeformel nur, wenn die Heimatstadt insgesamt ist
		if (!userName.equals("gesamt")) {
			return null;
		}

		//Datensatzgröße (Wert, der in der Datensatzzeile nach Summen sucht)
		final int dataSize = parent.getRecords().size() - 1;

		//Spaltenname
		final String colAlpha = CellReference.convertNumToColString(point.x);

		//Beginn des Gesamtwertes/Endzeilennummer
		final int startRowNumber = point.y - dataSize + 1;
		final int endRowNumber = point.y;

		return String.format("SUM(%s%d:%s%d)", colAlpha, startRowNumber, colAlpha, endRowNumber);

	}
}

@XlsFormula Wenn Sie im entsprechenden Feld einen Wert angeben, wird durch die Angabe von primary = false Priorität vergeben. Wenn true, hat die Formel immer Vorrang.

@XlsDefaultValue Setzen Sie den Standardwert für NULL mit value. Wenn case = ProcessCase.Save angegeben ist, wird der Standardwert nur zum Schreiben festgelegt.

Lauf

Geben Sie "date = 20190312" als Argument in die Ausführungskonfiguration der Springboot-App ein, wenden Sie sie an und führen Sie sie aus.

Ausführungsergebnis

Excel ausgeben

Wenn Sie sich das Formelfenster ansehen, wird die Formel auch ordnungsgemäß ausgegeben.

無題2.png

Log

Protokollieren Sie beim Lesen der Tabelle nach dem Schreiben. Die Erfassung erfolgt ordnungsgemäß.

Protokoll (Auszug)


com.example.demo.service.DemoService : date:2019-03-12
com.example.demo.service.DemoService : UsingListRecord(positions={userName=A5, price=B5, tax=C5, usingStartDate=D5, homeTown=E5, species=F5, ageAvg=G5, apprentice=H5}, parent=null, userName=Anakin Skywalker, price=120001, tax=1.08, usingStartDate=Sat Mar 02 00:00:00 JST 2019, homeTown=Tatween, species=Mensch, ageAvg=100, apprentice=Asoka Tano)
com.example.demo.service.DemoService : UsingListRecord(positions={userName=A6, price=B6, tax=C6, usingStartDate=D6, homeTown=E6, species=F6, ageAvg=G6, apprentice=H6}, parent=null, userName=Padme Amidara, price=120002, tax=2.08, usingStartDate=Sun Mar 03 00:00:00 JST 2019, homeTown=Naboo, species=Mensch, ageAvg=100, apprentice=--)
com.example.demo.service.DemoService : UsingListRecord(positions={userName=A7, price=B7, tax=C7, usingStartDate=D7, homeTown=E7, species=F7, ageAvg=G7, apprentice=H7}, parent=null, userName=Luke Skywalker, price=120003, tax=3.08, usingStartDate=Mon Mar 04 00:00:00 JST 2019, homeTown=Polizei Masa, species=Mensch, ageAvg=100, apprentice=Kairo Ren)
com.example.demo.service.DemoService : UsingListRecord(positions={userName=A8, price=B8, tax=C8, usingStartDate=D8, homeTown=E8, species=F8, ageAvg=G8, apprentice=H8}, parent=null, userName=Kairo Ren, price=120004, tax=4.08, usingStartDate=Tue Mar 05 00:00:00 JST 2019, homeTown=Chandrila, species=Mensch, ageAvg=100, apprentice=--)
com.example.demo.service.DemoService : UsingListRecord(positions={userName=A9, price=B9, tax=C9, usingStartDate=D9, homeTown=E9, species=F9, ageAvg=G9, apprentice=H9}, parent=null, userName=Asoka Tano, price=120005, tax=5.08, usingStartDate=Wed Mar 06 00:00:00 JST 2019, homeTown=Siri, species=Togruta, ageAvg=100, apprentice=--)
com.example.demo.service.DemoService : UsingListRecord(positions={userName=A10, price=B10, tax=C10, usingStartDate=D10, homeTown=E10, species=F10, ageAvg=G10, apprentice=H10}, parent=null, userName=Darth Mall, price=120006, tax=6.08, usingStartDate=Thu Mar 07 00:00:00 JST 2019, homeTown=Dasomia, species=Zabrak, ageAvg=null, apprentice=Wilde Opres)
com.example.demo.service.DemoService : UsingListRecord(positions={userName=A11, price=B11, tax=C11, usingStartDate=D11, homeTown=E11, species=F11, ageAvg=G11, apprentice=H11}, parent=null, userName=Yoda, price=120007, tax=7.08, usingStartDate=Fri Mar 08 00:00:00 JST 2019, homeTown=--, species=Yodaの種族, ageAvg=800, apprentice=Luke Skywalker)
com.example.demo.service.DemoService : UsingListRecord(positions={userName=A12, price=B12, tax=C12, usingStartDate=D12, homeTown=E12, species=F12, ageAvg=G12, apprentice=H12}, parent=null, userName=gesamt, price=840028, tax=null, usingStartDate=null, homeTown=--, species=null, ageAvg=null, apprentice=--)

Nachwort

Ich habe festgestellt, dass es implementiert wurde, aber es ist auch gut, dass der Abschlussprozess nicht erforderlich ist. Dieses Mal wurde es etwas kompliziert, da der Prozess zum Ausgeben der Formel (Gesamtzeile) im endgültigen Datensatz enthalten ist. Wenn jedoch keine Formel vorhanden ist, ist die Methode sowohl für die Blatt- als auch für die Datensatzklasse nicht erforderlich, und die Annotation wird reduziert und ist recht einfach. Werden.

Recommended Posts

Excel mit Formeln mit XlsMapper ausgeben
FizzBuzz mit Stream ausgeben
Ausgabe einer CSV-Datei mit offener CSV
Lassen Sie uns Excel mit Java betreiben! !!
Ausgabe neunundneunzig mit Stream
Steuerprotokollausgabe mit Doma2
Ausgabe "Izumi Oishi" mit Dokojava
Bearbeiten Sie Excel mit Apache POI
Ausgabe nach Excel mit Apache POI!
Ausgabezeichen wie Konversation mit JavaFX
Ausgabe Testabdeckung mit Klee + Gradle
Erstellen Sie eine Excel-Datei mit poi
PDF und TIFF mit Java 8 ausgeben
Beispiel für eine EXCEL-Dateiaktualisierung mit JAVA
Java fügt Excel-Formeln hinzu und liest sie