본문 바로가기
Mendix/Document

[Jxls] jxls-2.14.0.jar에서 jxls-3.0.0.jar로 변경하기

by dya0 2024. 11. 26.

출처: 

마이그레이션 방법: https://jxls.sourceforge.net/migration-to-v3-0.html

Jxls 사용법: https://jxls.sourceforge.net/getting-started.html

https://jxls.sourceforge.net/builder.html

 

주요 변경사항 

- JxlsHelper -> new builder API

 - All options can now be set in the builder with a Fluent API

- The TransformerFactory and createTransformer() methods have also been removed.

등등등 문서 보면 나옴.

 

결론 

① userlib에 기존 파일 삭제 jxls

삭제한 기존 파일
추가한 jar 파일

 

 

② 코드 수정 

jxlser>implements>JxlserProcessor.java 만 수정하면 된다.

package jxlser.implementation;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.jxls.command.ImageCommand;
import org.jxls.transform.poi.JxlsPoiTemplateFillerBuilder;

import com.mendix.core.Core;
import com.mendix.systemwideinterfaces.core.IContext;
import com.mendix.systemwideinterfaces.core.IMendixObject;
import com.mendix.systemwideinterfaces.core.meta.IMetaObject;

import system.proxies.FileDocument;

public class JxlserProcessor {

	public static void doProcessTemplate(IContext mxcontext, InputStream templateIs, FileDocument mergedXlsFile, String targetCell) throws Exception {
		try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {

			Map<String, Object> jxcontext = new HashMap<String, Object>();
	        Map<String, Object> params = JxlserParameterUtil.getNextParameters();

	        for (String key : params.keySet()) {
	            Object param = params.get(key);

	            if (param instanceof List) {
	                List<IMendixObject> moList = (List<IMendixObject>)param;
	                List<Object> proxyList = new ArrayList<Object>();

	                for (IMendixObject mo: moList) {
	                    proxyList.add(toProxyObject(mxcontext, mo));
	                }

	                jxcontext.put(key, proxyList);
	            } else {
	                jxcontext.put(key, toProxyObject(mxcontext, (IMendixObject)params.get(key)));
	            }
	        }

	        File temp = File.createTempFile("template_", ".xls"); // 임시 파일 생성
	        temp.deleteOnExit(); // 프로그램 종료 시 임시 파일 삭제

	        if (targetCell != null && !targetCell.equals("")) {
	            JxlsPoiTemplateFillerBuilder.newInstance().withTemplate(templateIs).buildAndFill(jxcontext, temp);
	        } else {
	            JxlsPoiTemplateFillerBuilder.newInstance().withTemplate(templateIs).buildAndFill(jxcontext, temp);
	        }

	        Core.storeFileDocumentContent(mxcontext, mergedXlsFile.getMendixObject(),
	                new ByteArrayInputStream(FileUtils.readFileToByteArray(temp)));
	    } catch (IOException e) {
	        e.printStackTrace();

		}
	}

	private static Object toProxyObject(IContext mxcontext, IMendixObject mo) throws Exception
	{
		if (mo == null) {
			return null;
		}

		IMetaObject meta = mo.getMetaObject();
		if (meta.getSuperObject() != null && meta.getSuperObject().getName().equals("System.Image")) {
			InputStream is = Core.getImage(mxcontext, mo, false);
			return ImageCommand.toByteArray(is);
		} else {
			String proxyClassName = meta.getModuleName().toLowerCase() + ".proxies." + meta.getName().replace(meta.getModuleName()+".", "");
		    Class clazz = Class.forName(proxyClassName);
		    Method initializeer = clazz.getDeclaredMethod("initialize", IContext.class, IMendixObject.class);
		    Object proxy = initializeer.invoke(null, mxcontext, mo);
		    return proxy;
		}
	}

}

 

 

③ Excel 파일 작성

메모를 잘 작성해야 제대로 나온다.

 

direction="RIGHT"을 쓰기위해서는 lastCell을 정확하게 줘야한다. lastCell="C3"으로 주면 공백도 같이 반복된다.
name1 빈칸  name2 빈칸 name3 빈칸 이런식으로 반영된다.  

 

④ MF 작성 

① Add Jxls Context Prameter

 

② Process Jxls Template By File Document

결과 화면 

DB에 저장된 값

 

Excel에 출력된 값

==

과정

userlib에 파일을 변경한 후 실행을 시키면 에러가 발생한다. 

C:\Users\YourPCName\Mendix\SampleApp-branch-poi-upgrade\javasource\jxlser\implementation\JxlserProcessor.java:12: error: cannot find symbol
import org.jxls.util.JxlsHelper;
                    ^
  symbol:   class JxlsHelper
  location: package org.jxls.util
C:\Users\YourPCName\Mendix\SampleApp-branch-poi-upgrade\javasource\jxlser\implementation\JxlserProcessor.java:13: error: cannot find symbol
import org.jxls.util.Util;
                    ^
  symbol:   class Util
  location: package org.jxls.util
C:\Users\YourPCName\Mendix\SampleApp-branch-poi-upgrade\javasource\jxlser\implementation\JxlserProcessor.java:27: error: Context is abstract; cannot be instantiated
			org.jxls.common.Context jxcontext = new org.jxls.common.Context();
			                                    ^
C:\Users\YourPCName\Mendix\SampleApp-branch-poi-upgrade\javasource\jxlser\implementation\JxlserProcessor.java:43: error: cannot find symbol
            	JxlsHelper.getInstance().processTemplateAtCell(templateIs, os, jxcontext, targetCell);
            	^
  symbol:   variable JxlsHelper
  location: class JxlserProcessor
C:\Users\YourPCName\Mendix\SampleApp-branch-poi-upgrade\javasource\jxlser\implementation\JxlserProcessor.java:45: error: cannot find symbol
            	JxlsHelper.getInstance().processTemplate(templateIs, os, jxcontext);
            	^
  symbol:   variable JxlsHelper
  location: class JxlserProcessor
C:\Users\YourPCName\Mendix\SampleApp-branch-poi-upgrade\javasource\jxlser\implementation\JxlserProcessor.java:64: error: cannot find symbol
			return Util.toByteArray(is);
			       ^
  symbol:   variable Util
  location: class JxlserProcessor
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
6 errors

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compile'.
> Compilation failed; see the compiler error output for details.

* Try:
> Run with --scan to get full insights.

BUILD FAILED in 1s

 

마켓플레이스에서 다운로드 받은 Jxls에서 문제가 발생한다. Exclipse를 실행하여 해당 파일을 찾는다.

jxlser.implementaion > JxlserProcessor.java

package jxlser.implementation;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.jxls.util.JxlsHelper;
import org.jxls.util.Util;

import com.mendix.core.Core;
import com.mendix.systemwideinterfaces.core.IContext;
import com.mendix.systemwideinterfaces.core.IMendixObject;
import com.mendix.systemwideinterfaces.core.meta.IMetaObject;

import system.proxies.FileDocument;

 

먼저 import 를 보면 문제가 되는 영역은 아래와 같다. 

import org.jxls.util.JxlsHelper;
import org.jxls.util.Util;

3.0.0으로 변경하면서 util이 변경되어 찾을 수 없어 에러가 발생한다. 둘 다 사용 불가함으로 삭제한다. 

 

Context 대신 Map<String, Object> (이를 "data"라고 함)을 사용한다.
특별한 Map 동작이 필요한 경우 MapDelegator<String, Object>를 기본 클래스로 사용할 수 있다. 하나 또는 몇 개의 메서드를 덮어쓰기만 하면 된다.

Context.putVar() 대신 Map.put()을 호출한다. 이와 같은 호출이 많으면 putVar() 메서드로 자체 HashMap 구현을 만들 수 있습니다.

 

 

Util.toByteArray() has been moved to ImageCommand. There's also a useful copy(InputStream, OutputStream) method in ImageCommand.

 

jx:params(formulaStrategy="BY_COLUMN")

 

https://jxls.sourceforge.net/javadoc/jxls/org/jxls/util/JxlsHelper.html#processTemplateAtCell-java.io.InputStream-java.io.OutputStream-org.jxls.common.Context-java.lang.String-

 

 

https://jxls.sourceforge.net/javadoc/jxls/org/jxls/util/JxlsHelper.html#processTemplate-java.io.InputStream-java.io.OutputStream-org.jxls.common.Context-