├── .dockerignore ├── .github └── workflows │ ├── release-build-linux.yml │ ├── release-build-native-macos.yml │ └── release-build-native-win64.yml ├── .gitignore ├── .mvn └── wrapper │ ├── MavenWrapperDownloader.java │ └── maven-wrapper.properties ├── .travis.yml ├── LICENSE ├── README.adoc ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── main ├── docker │ ├── Dockerfile.fast-jar │ ├── Dockerfile.jvm │ └── Dockerfile.native ├── kotlin │ └── fr │ │ └── ncomet │ │ └── Main.kt └── resources │ └── application.properties └── test ├── kotlin └── fr │ └── ncomet │ └── MainTest.kt └── resources ├── empty-file.csv ├── empty-file.xlsx ├── file-3-sheets-shifted.xlsx ├── file-3-sheets.xlsx ├── file-every-cell-types.xlsx ├── file-shifted.csv ├── file-shifted.xlsx ├── file.adoc ├── file.csv ├── file.test └── file.xlsx /.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !target/*-runner 3 | !target/*-runner.jar 4 | !target/lib/* 5 | !target/quarkus-app/* -------------------------------------------------------------------------------- /.github/workflows/release-build-linux.yml: -------------------------------------------------------------------------------- 1 | name: release-build-linux 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | jobs: 8 | build: 9 | 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Install graalvm 15 | uses: DeLaGuardo/setup-graalvm@master 16 | with: 17 | graalvm-version: '20.2.0.java11' 18 | - name: Install native-image 19 | run: gu install native-image 20 | - name: Set version 21 | run: ./mvnw versions:set -DnewVersion="${{ github.event.release.tag_name }}" 22 | - name: Build jvm jar 23 | run: ./mvnw package 24 | - name: Upload jvm 25 | id: upload-jar 26 | uses: actions/upload-release-asset@v1 27 | env: 28 | GITHUB_TOKEN: ${{ secrets.RELEASE_SECRET }} 29 | with: 30 | upload_url: ${{ github.event.release.upload_url }} 31 | asset_path: ./target/excel2adoc-${{ github.event.release.tag_name }}-runner.jar 32 | asset_name: excel2adoc-${{ github.event.release.tag_name }}.jar 33 | asset_content_type: application/octet-stream 34 | - name: Build native executable 35 | run: ./mvnw package -Dnative 36 | - name: Upload native executable 37 | id: upload-native-executable 38 | uses: actions/upload-release-asset@v1 39 | env: 40 | GITHUB_TOKEN: ${{ secrets.RELEASE_SECRET }} 41 | with: 42 | upload_url: ${{ github.event.release.upload_url }} 43 | asset_path: ./target/excel2adoc-${{ github.event.release.tag_name }}-runner 44 | asset_name: excel2adoc-${{ github.event.release.tag_name }}-linux 45 | asset_content_type: application/octet-stream -------------------------------------------------------------------------------- /.github/workflows/release-build-native-macos.yml: -------------------------------------------------------------------------------- 1 | name: release-build-native-macos 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | jobs: 8 | build: 9 | 10 | runs-on: macos-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Install graalvm 15 | uses: DeLaGuardo/setup-graalvm@master 16 | with: 17 | graalvm-version: '20.2.0.java11' 18 | - name: Install native-image 19 | run: gu install native-image 20 | - name: Set version 21 | run: ./mvnw versions:set -DnewVersion="${{ github.event.release.tag_name }}" 22 | - name: Build native executable 23 | run: ./mvnw package -Dnative 24 | - name: Upload native executable 25 | id: upload-native-image-macos 26 | uses: actions/upload-release-asset@v1 27 | env: 28 | GITHUB_TOKEN: ${{ secrets.RELEASE_SECRET }} 29 | with: 30 | upload_url: ${{ github.event.release.upload_url }} 31 | asset_path: ./target/excel2adoc-${{ github.event.release.tag_name }}-runner 32 | asset_name: excel2adoc-${{ github.event.release.tag_name }}-macos 33 | asset_label: macos 34 | asset_content_type: application/octet-stream -------------------------------------------------------------------------------- /.github/workflows/release-build-native-win64.yml: -------------------------------------------------------------------------------- 1 | name: release-build-native-win64 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | jobs: 8 | build: 9 | 10 | runs-on: windows-2019 11 | 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Install graalvm 15 | uses: DeLaGuardo/setup-graalvm@master 16 | with: 17 | graalvm-version: '20.2.0.java11' 18 | - name: Install native-image 19 | run: | 20 | %JAVA_HOME%/bin/gu.cmd install native-image 21 | shell: cmd 22 | - name: Configure Pagefile 23 | # Increased the page-file size due to memory-consumption of native-image command 24 | # For details see https://github.com/actions/virtual-environments/issues/785 25 | uses: al-cheb/configure-pagefile-action@v1.2 26 | - name: Set version 27 | run: mvnw versions:set -DnewVersion="${{ github.event.release.tag_name }}" 28 | shell: cmd 29 | - name: Build native executable 30 | # Invoke the native-image build with the necessary Visual Studio tooling/environment intialized 31 | run: | 32 | call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64 33 | mvnw package -Dnative" 34 | shell: cmd 35 | - name: Upload native executable 36 | id: upload-native-executable 37 | uses: actions/upload-release-asset@v1 38 | env: 39 | GITHUB_TOKEN: ${{ secrets.RELEASE_SECRET }} 40 | with: 41 | upload_url: ${{ github.event.release.upload_url }} 42 | asset_path: target/excel2adoc-${{ github.event.release.tag_name }}-runner.exe 43 | asset_name: excel2adoc-${{ github.event.release.tag_name }}-win64.exe 44 | asset_label: win64 45 | asset_content_type: application/octet-stream -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #Maven 2 | target/ 3 | pom.xml.tag 4 | pom.xml.releaseBackup 5 | pom.xml.versionsBackup 6 | release.properties 7 | 8 | # Eclipse 9 | .project 10 | .classpath 11 | .settings/ 12 | bin/ 13 | 14 | # IntelliJ 15 | .idea 16 | *.ipr 17 | *.iml 18 | *.iws 19 | 20 | # NetBeans 21 | nb-configuration.xml 22 | 23 | # Visual Studio Code 24 | .vscode 25 | .factorypath 26 | 27 | # OSX 28 | .DS_Store 29 | 30 | # Vim 31 | *.swp 32 | *.swo 33 | 34 | # patch 35 | *.orig 36 | *.rej 37 | -------------------------------------------------------------------------------- /.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007-present the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import java.net.*; 17 | import java.io.*; 18 | import java.nio.channels.*; 19 | import java.util.Properties; 20 | 21 | public class MavenWrapperDownloader { 22 | 23 | private static final String WRAPPER_VERSION = "0.5.6"; 24 | /** 25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 26 | */ 27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" 28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; 29 | 30 | /** 31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 32 | * use instead of the default one. 33 | */ 34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 35 | ".mvn/wrapper/maven-wrapper.properties"; 36 | 37 | /** 38 | * Path where the maven-wrapper.jar will be saved to. 39 | */ 40 | private static final String MAVEN_WRAPPER_JAR_PATH = 41 | ".mvn/wrapper/maven-wrapper.jar"; 42 | 43 | /** 44 | * Name of the property which should be used to override the default download url for the wrapper. 45 | */ 46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 47 | 48 | public static void main(String args[]) { 49 | System.out.println("- Downloader started"); 50 | File baseDirectory = new File(args[0]); 51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 52 | 53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 54 | // wrapperUrl parameter. 55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 56 | String url = DEFAULT_DOWNLOAD_URL; 57 | if(mavenWrapperPropertyFile.exists()) { 58 | FileInputStream mavenWrapperPropertyFileInputStream = null; 59 | try { 60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 61 | Properties mavenWrapperProperties = new Properties(); 62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 64 | } catch (IOException e) { 65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 66 | } finally { 67 | try { 68 | if(mavenWrapperPropertyFileInputStream != null) { 69 | mavenWrapperPropertyFileInputStream.close(); 70 | } 71 | } catch (IOException e) { 72 | // Ignore ... 73 | } 74 | } 75 | } 76 | System.out.println("- Downloading from: " + url); 77 | 78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 79 | if(!outputFile.getParentFile().exists()) { 80 | if(!outputFile.getParentFile().mkdirs()) { 81 | System.out.println( 82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 83 | } 84 | } 85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 86 | try { 87 | downloadFileFromURL(url, outputFile); 88 | System.out.println("Done"); 89 | System.exit(0); 90 | } catch (Throwable e) { 91 | System.out.println("- Error downloading"); 92 | e.printStackTrace(); 93 | System.exit(1); 94 | } 95 | } 96 | 97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { 99 | String username = System.getenv("MVNW_USERNAME"); 100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); 101 | Authenticator.setDefault(new Authenticator() { 102 | @Override 103 | protected PasswordAuthentication getPasswordAuthentication() { 104 | return new PasswordAuthentication(username, password); 105 | } 106 | }); 107 | } 108 | URL website = new URL(urlString); 109 | ReadableByteChannel rbc; 110 | rbc = Channels.newChannel(website.openStream()); 111 | FileOutputStream fos = new FileOutputStream(destination); 112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 113 | fos.close(); 114 | rbc.close(); 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: openjdk11 3 | 4 | after_success: 5 | - bash <(curl -s https://codecov.io/bash) 6 | 7 | cache: 8 | directories: 9 | - $HOME/.m2 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Nicolas Comet 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = excel2adoc CLI 2 | 3 | image:https://travis-ci.com/ncomet/excel2adoc.svg?branch=master["excel2adoc build", link="https://travis-ci.com/ncomet/excel2adoc"] image:https://codecov.io/gh/ncomet/excel2adoc/branch/master/graph/badge.svg["excel2adoc coverage", link="https://codecov.io/gh/ncomet/excel2adoc"] 4 | 5 | A CLI that prints .xlsx or .csv file(s) into their asciidoc representation on stdout 6 | 7 | == User guide 8 | 9 | `$ excel2adoc -h` 10 | 11 | [code, bash] 12 | ---- 13 | Usage: excel2adoc [-hntV] [-s=2] ... 14 | Prints .xlsx or .csv file(s) into their asciidoc representation on stdout 15 | ... One or more .xlsx or .csv file(s) to print to stdout 16 | -h, --help Show this help message and exit. 17 | -n, --no-headers Disables interpretation of first row as header 18 | Default: false 19 | -s, --sheet=2 Sheet number, starting at 1. if not provided, it will 20 | try to print all sheets for all files 21 | -t, --no-titles Disables table title using file name and sheet name (or 22 | just file name for .csv) 23 | Default: false 24 | -V, --version Print version information and exit. 25 | ---- 26 | 27 | == Releases 28 | 29 | The binaries (linux, macOS and windows) can be found on https://github.com/ncomet/excel2adoc/releases[this project release page] 30 | 31 | == Why? 32 | 33 | Because we all know product managers, project managers, timetable reporters that only swear by _Excel_ to provide us with some insightful piece of information. 34 | 35 | Let's get real: if we want it to work, we use https://www.oreilly.com/library/view/living-documentation-continuous/9780134689418/[documentation as code,window=_blank], not binaries. 36 | 37 | Here is a CLI tool to convert to the real deal, *text*. Just text, that will find all its use under a proper CVS. 38 | 39 | == How does it work? 40 | 41 | This project uses Quarkus, the Supersonic Subatomic Framework, https://poi.apache.org/[Apache POI], https://kotlinlang.org/[Kotlin] and https://github.com/remkop/picocli[picocli] (https://quarkus.io/guides/picocli[Quarkus picocli extension]). 42 | 43 | If you want to learn more about Quarkus, please visit its website: https://quarkus.io/[window=_blank] 44 | 45 | == Running the application in dev mode 46 | 47 | You can run your application in dev mode that enables live coding using: 48 | 49 | [source,shell script] 50 | ---- 51 | ./mvnw compile quarkus:dev 52 | 53 | ---- 54 | 55 | == Packaging and running the application 56 | 57 | The application can be packaged using: 58 | 59 | [source,shell script] 60 | ---- 61 | ./mvnw package 62 | ---- 63 | 64 | It produces the `excel2adoc-1.0-runner.jar` file in the `/target` directory. 65 | Be aware that it’s not an _über-jar_ as the dependencies are copied into the `target/lib` directory. 66 | 67 | If you want to build an _über-jar_, execute the following command: 68 | 69 | [source,shell script] 70 | ---- 71 | ./mvnw package -Dquarkus.package.type=uber-jar 72 | ---- 73 | 74 | The application is now runnable using `java -jar target/excel2adoc-1.0-runner.jar`. 75 | 76 | == Creating a native executable 77 | 78 | You can create a native executable using: 79 | 80 | [source,shell script] 81 | ---- 82 | ./mvnw package -Pnative 83 | ---- 84 | 85 | Or, if you don't have GraalVM installed, you can run the native executable build in a container using: 86 | 87 | [source,shell script] 88 | ---- 89 | ./mvnw package -Pnative -Dquarkus.native.container-build=true 90 | ---- 91 | 92 | You can then execute your native executable with: `./target/excel2adoc-1.0-runner` 93 | 94 | If you want to learn more about building native executables, please consult https://quarkus.io/guides/maven-tooling.html[window=_blank] 95 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Mingw, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | fi 118 | 119 | if [ -z "$JAVA_HOME" ]; then 120 | javaExecutable="`which javac`" 121 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 122 | # readlink(1) is not available as standard on Solaris 10. 123 | readLink=`which readlink` 124 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 125 | if $darwin ; then 126 | javaHome="`dirname \"$javaExecutable\"`" 127 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 128 | else 129 | javaExecutable="`readlink -f \"$javaExecutable\"`" 130 | fi 131 | javaHome="`dirname \"$javaExecutable\"`" 132 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 133 | JAVA_HOME="$javaHome" 134 | export JAVA_HOME 135 | fi 136 | fi 137 | fi 138 | 139 | if [ -z "$JAVACMD" ] ; then 140 | if [ -n "$JAVA_HOME" ] ; then 141 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 142 | # IBM's JDK on AIX uses strange locations for the executables 143 | JAVACMD="$JAVA_HOME/jre/sh/java" 144 | else 145 | JAVACMD="$JAVA_HOME/bin/java" 146 | fi 147 | else 148 | JAVACMD="`which java`" 149 | fi 150 | fi 151 | 152 | if [ ! -x "$JAVACMD" ] ; then 153 | echo "Error: JAVA_HOME is not defined correctly." >&2 154 | echo " We cannot execute $JAVACMD" >&2 155 | exit 1 156 | fi 157 | 158 | if [ -z "$JAVA_HOME" ] ; then 159 | echo "Warning: JAVA_HOME environment variable is not set." 160 | fi 161 | 162 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 163 | 164 | # traverses directory structure from process work directory to filesystem root 165 | # first directory with .mvn subdirectory is considered project base directory 166 | find_maven_basedir() { 167 | 168 | if [ -z "$1" ] 169 | then 170 | echo "Path not specified to find_maven_basedir" 171 | return 1 172 | fi 173 | 174 | basedir="$1" 175 | wdir="$1" 176 | while [ "$wdir" != '/' ] ; do 177 | if [ -d "$wdir"/.mvn ] ; then 178 | basedir=$wdir 179 | break 180 | fi 181 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 182 | if [ -d "${wdir}" ]; then 183 | wdir=`cd "$wdir/.."; pwd` 184 | fi 185 | # end of workaround 186 | done 187 | echo "${basedir}" 188 | } 189 | 190 | # concatenates all lines of a file 191 | concat_lines() { 192 | if [ -f "$1" ]; then 193 | echo "$(tr -s '\n' ' ' < "$1")" 194 | fi 195 | } 196 | 197 | BASE_DIR=`find_maven_basedir "$(pwd)"` 198 | if [ -z "$BASE_DIR" ]; then 199 | exit 1; 200 | fi 201 | 202 | ########################################################################################## 203 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 204 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 205 | ########################################################################################## 206 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then 207 | if [ "$MVNW_VERBOSE" = true ]; then 208 | echo "Found .mvn/wrapper/maven-wrapper.jar" 209 | fi 210 | else 211 | if [ "$MVNW_VERBOSE" = true ]; then 212 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." 213 | fi 214 | if [ -n "$MVNW_REPOURL" ]; then 215 | jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 216 | else 217 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 218 | fi 219 | while IFS="=" read key value; do 220 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;; 221 | esac 222 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" 223 | if [ "$MVNW_VERBOSE" = true ]; then 224 | echo "Downloading from: $jarUrl" 225 | fi 226 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" 227 | if $cygwin; then 228 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` 229 | fi 230 | 231 | if command -v wget > /dev/null; then 232 | if [ "$MVNW_VERBOSE" = true ]; then 233 | echo "Found wget ... using wget" 234 | fi 235 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 236 | wget "$jarUrl" -O "$wrapperJarPath" 237 | else 238 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" 239 | fi 240 | elif command -v curl > /dev/null; then 241 | if [ "$MVNW_VERBOSE" = true ]; then 242 | echo "Found curl ... using curl" 243 | fi 244 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 245 | curl -o "$wrapperJarPath" "$jarUrl" -f 246 | else 247 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f 248 | fi 249 | 250 | else 251 | if [ "$MVNW_VERBOSE" = true ]; then 252 | echo "Falling back to using Java to download" 253 | fi 254 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" 255 | # For Cygwin, switch paths to Windows format before running javac 256 | if $cygwin; then 257 | javaClass=`cygpath --path --windows "$javaClass"` 258 | fi 259 | if [ -e "$javaClass" ]; then 260 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 261 | if [ "$MVNW_VERBOSE" = true ]; then 262 | echo " - Compiling MavenWrapperDownloader.java ..." 263 | fi 264 | # Compiling the Java class 265 | ("$JAVA_HOME/bin/javac" "$javaClass") 266 | fi 267 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 268 | # Running the downloader 269 | if [ "$MVNW_VERBOSE" = true ]; then 270 | echo " - Running MavenWrapperDownloader.java ..." 271 | fi 272 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") 273 | fi 274 | fi 275 | fi 276 | fi 277 | ########################################################################################## 278 | # End of extension 279 | ########################################################################################## 280 | 281 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 282 | if [ "$MVNW_VERBOSE" = true ]; then 283 | echo $MAVEN_PROJECTBASEDIR 284 | fi 285 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 286 | 287 | # For Cygwin, switch paths to Windows format before running java 288 | if $cygwin; then 289 | [ -n "$M2_HOME" ] && 290 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 291 | [ -n "$JAVA_HOME" ] && 292 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 293 | [ -n "$CLASSPATH" ] && 294 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 295 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 296 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 297 | fi 298 | 299 | # Provide a "standardized" way to retrieve the CLI args that will 300 | # work with both Windows and non-Windows executions. 301 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 302 | export MAVEN_CMD_LINE_ARGS 303 | 304 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 305 | 306 | exec "$JAVACMD" \ 307 | $MAVEN_OPTS \ 308 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 309 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 310 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 311 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 124 | 125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 127 | ) 128 | 129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 131 | if exist %WRAPPER_JAR% ( 132 | if "%MVNW_VERBOSE%" == "true" ( 133 | echo Found %WRAPPER_JAR% 134 | ) 135 | ) else ( 136 | if not "%MVNW_REPOURL%" == "" ( 137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 138 | ) 139 | if "%MVNW_VERBOSE%" == "true" ( 140 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 141 | echo Downloading from: %DOWNLOAD_URL% 142 | ) 143 | 144 | powershell -Command "&{"^ 145 | "$webclient = new-object System.Net.WebClient;"^ 146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 148 | "}"^ 149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ 150 | "}" 151 | if "%MVNW_VERBOSE%" == "true" ( 152 | echo Finished downloading %WRAPPER_JAR% 153 | ) 154 | ) 155 | @REM End of extension 156 | 157 | @REM Provide a "standardized" way to retrieve the CLI args that will 158 | @REM work with both Windows and non-Windows executions. 159 | set MAVEN_CMD_LINE_ARGS=%* 160 | 161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 162 | if ERRORLEVEL 1 goto error 163 | goto end 164 | 165 | :error 166 | set ERROR_CODE=1 167 | 168 | :end 169 | @endlocal & set ERROR_CODE=%ERROR_CODE% 170 | 171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 175 | :skipRcPost 176 | 177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 179 | 180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 181 | 182 | exit /B %ERROR_CODE% 183 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | fr.ncomet 6 | excel2adoc 7 | 1.1 8 | 9 | 3.8.1 10 | 1.3.72 11 | true 12 | 11 13 | 11 14 | UTF-8 15 | UTF-8 16 | 1.10.3.Final 17 | quarkus-universe-bom 18 | io.quarkus 19 | 1.10.3.Final 20 | 2.22.1 21 | 0.8.6 22 | 23 | 24 | 25 | 26 | ${quarkus.platform.group-id} 27 | ${quarkus.platform.artifact-id} 28 | ${quarkus.platform.version} 29 | pom 30 | import 31 | 32 | 33 | 34 | 35 | 36 | io.quarkus 37 | quarkus-picocli 38 | 39 | 40 | io.quarkus 41 | quarkus-kotlin 42 | 43 | 44 | org.apache.poi 45 | poi 46 | 4.1.2 47 | 48 | 49 | org.apache.poi 50 | poi-ooxml 51 | 4.1.2 52 | 53 | 54 | org.apache.poi 55 | ooxml-schemas 56 | 1.4 57 | 58 | 59 | org.apache.poi 60 | poi-ooxml-schemas 61 | 4.1.2 62 | 63 | 64 | org.jetbrains.kotlin 65 | kotlin-stdlib-jdk8 66 | 67 | 68 | io.quarkus 69 | quarkus-junit5 70 | test 71 | 72 | 73 | org.junit-pioneer 74 | junit-pioneer 75 | 1.1.0 76 | test 77 | 78 | 79 | org.assertj 80 | assertj-core 81 | 3.18.1 82 | test 83 | 84 | 85 | com.ginsberg 86 | junit5-system-exit 87 | 1.0.0 88 | test 89 | 90 | 91 | 92 | src/main/kotlin 93 | src/test/kotlin 94 | 95 | 96 | io.quarkus 97 | quarkus-maven-plugin 98 | ${quarkus-plugin.version} 99 | true 100 | 101 | 102 | 103 | build 104 | generate-code 105 | generate-code-tests 106 | 107 | 108 | 109 | 110 | 111 | maven-compiler-plugin 112 | ${compiler-plugin.version} 113 | 114 | 115 | maven-surefire-plugin 116 | ${surefire-plugin.version} 117 | 118 | 119 | org.jboss.logmanager.LogManager 120 | ${maven.home} 121 | 122 | 123 | 124 | 125 | org.jetbrains.kotlin 126 | kotlin-maven-plugin 127 | ${kotlin.version} 128 | 129 | 130 | compile 131 | 132 | compile 133 | 134 | 135 | 136 | test-compile 137 | 138 | test-compile 139 | 140 | 141 | 142 | 143 | 144 | org.jetbrains.kotlin 145 | kotlin-maven-allopen 146 | ${kotlin.version} 147 | 148 | 149 | 150 | true 151 | 1.8 152 | 153 | all-open 154 | 155 | 156 | 157 | 158 | org.jacoco 159 | jacoco-maven-plugin 160 | ${jacoco-maven-plugin.version} 161 | 162 | 163 | 164 | prepare-agent 165 | 166 | 167 | 168 | report 169 | test 170 | 171 | report 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | native 181 | 182 | 183 | native 184 | 185 | 186 | 187 | 188 | 189 | maven-failsafe-plugin 190 | ${surefire-plugin.version} 191 | 192 | 193 | 194 | integration-test 195 | verify 196 | 197 | 198 | 199 | ${project.build.directory}/${project.build.finalName}-runner 200 | org.jboss.logmanager.LogManager 201 | ${maven.home} 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | native 211 | 212 | 213 | 214 | 215 | -------------------------------------------------------------------------------- /src/main/docker/Dockerfile.fast-jar: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode 3 | # 4 | # Before building the container image run: 5 | # 6 | # ./mvnw package -Dquarkus.package.type=fast-jar 7 | # 8 | # Then, build the image with: 9 | # 10 | # docker build -f src/main/docker/Dockerfile.fast-jar -t quarkus/excel2adoc-fast-jar . 11 | # 12 | # Then run the container using: 13 | # 14 | # docker run -i --rm -p 8080:8080 quarkus/excel2adoc-fast-jar 15 | # 16 | # If you want to include the debug port into your docker image 17 | # you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5050 18 | # 19 | # Then run the container using : 20 | # 21 | # docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/excel2adoc-fast-jar 22 | # 23 | ### 24 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3 25 | 26 | ARG JAVA_PACKAGE=java-11-openjdk-headless 27 | ARG RUN_JAVA_VERSION=1.3.8 28 | ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' 29 | # Install java and the run-java script 30 | # Also set up permissions for user `1001` 31 | RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \ 32 | && microdnf update \ 33 | && microdnf clean all \ 34 | && mkdir /deployments \ 35 | && chown 1001 /deployments \ 36 | && chmod "g+rwX" /deployments \ 37 | && chown 1001:root /deployments \ 38 | && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ 39 | && chown 1001 /deployments/run-java.sh \ 40 | && chmod 540 /deployments/run-java.sh \ 41 | && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security 42 | 43 | # Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. 44 | ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" 45 | # We make four distinct layers so if there are application changes the library layers can be re-used 46 | COPY --chown=1001 target/quarkus-app/lib/ /deployments/lib/ 47 | COPY --chown=1001 target/quarkus-app/*.jar /deployments/ 48 | COPY --chown=1001 target/quarkus-app/app/ /deployments/app/ 49 | COPY --chown=1001 target/quarkus-app/quarkus/ /deployments/quarkus/ 50 | 51 | EXPOSE 8080 52 | USER 1001 53 | 54 | ENTRYPOINT [ "/deployments/run-java.sh" ] 55 | -------------------------------------------------------------------------------- /src/main/docker/Dockerfile.jvm: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode 3 | # 4 | # Before building the container image run: 5 | # 6 | # ./mvnw package 7 | # 8 | # Then, build the image with: 9 | # 10 | # docker build -f src/main/docker/Dockerfile.jvm -t quarkus/excel2adoc-jvm . 11 | # 12 | # Then run the container using: 13 | # 14 | # docker run -i --rm -p 8080:8080 quarkus/excel2adoc-jvm 15 | # 16 | # If you want to include the debug port into your docker image 17 | # you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5050 18 | # 19 | # Then run the container using : 20 | # 21 | # docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/excel2adoc-jvm 22 | # 23 | ### 24 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3 25 | 26 | ARG JAVA_PACKAGE=java-11-openjdk-headless 27 | ARG RUN_JAVA_VERSION=1.3.8 28 | ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' 29 | # Install java and the run-java script 30 | # Also set up permissions for user `1001` 31 | RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \ 32 | && microdnf update \ 33 | && microdnf clean all \ 34 | && mkdir /deployments \ 35 | && chown 1001 /deployments \ 36 | && chmod "g+rwX" /deployments \ 37 | && chown 1001:root /deployments \ 38 | && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ 39 | && chown 1001 /deployments/run-java.sh \ 40 | && chmod 540 /deployments/run-java.sh \ 41 | && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security 42 | 43 | # Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. 44 | ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" 45 | COPY target/lib/* /deployments/lib/ 46 | COPY target/*-runner.jar /deployments/app.jar 47 | 48 | EXPOSE 8080 49 | USER 1001 50 | 51 | ENTRYPOINT [ "/deployments/run-java.sh" ] 52 | -------------------------------------------------------------------------------- /src/main/docker/Dockerfile.native: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode 3 | # 4 | # Before building the container image run: 5 | # 6 | # ./mvnw package -Pnative 7 | # 8 | # Then, build the image with: 9 | # 10 | # docker build -f src/main/docker/Dockerfile.native -t quarkus/excel2adoc . 11 | # 12 | # Then run the container using: 13 | # 14 | # docker run -i --rm -p 8080:8080 quarkus/excel2adoc 15 | # 16 | ### 17 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3 18 | WORKDIR /work/ 19 | RUN chown 1001 /work \ 20 | && chmod "g+rwX" /work \ 21 | && chown 1001:root /work 22 | COPY --chown=1001:root target/*-runner /work/application 23 | 24 | EXPOSE 8080 25 | USER 1001 26 | 27 | CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] 28 | -------------------------------------------------------------------------------- /src/main/kotlin/fr/ncomet/Main.kt: -------------------------------------------------------------------------------- 1 | package fr.ncomet 2 | 3 | import org.apache.poi.ss.usermodel.Cell 4 | import org.apache.poi.ss.usermodel.CellType.* 5 | import org.apache.poi.ss.usermodel.Row 6 | import org.apache.poi.ss.usermodel.Sheet 7 | import org.apache.poi.xssf.usermodel.XSSFWorkbook 8 | import picocli.CommandLine 9 | import picocli.CommandLine.* 10 | import picocli.CommandLine.Help.Visibility.ALWAYS 11 | import picocli.CommandLine.Model.CommandSpec 12 | import java.io.File 13 | import java.io.FileInputStream 14 | import java.lang.System.lineSeparator 15 | import java.util.concurrent.Callable 16 | import kotlin.system.exitProcess 17 | 18 | val allowedFileExtensions = listOf("xlsx", "csv") 19 | 20 | fun main(args: Array): Unit = exitProcess(command(args)) 21 | 22 | @Command( 23 | name = "excel2adoc", 24 | mixinStandardHelpOptions = true, 25 | version = ["excel2adoc v1.0"], 26 | description = ["Prints .xlsx or .csv file(s) into their asciidoc representation on stdout"] 27 | ) 28 | class Excel2Asciidoc : Callable { 29 | 30 | @Spec 31 | lateinit var out: CommandSpec 32 | 33 | @Parameters( 34 | index = "0", 35 | description = ["One or more .xlsx or .csv file(s) to print to stdout"], 36 | arity = "1..*" 37 | ) 38 | lateinit var inputFiles: List 39 | 40 | @Option( 41 | names = ["-n", "--no-headers"], 42 | description = ["Disables interpretation of first row as header"], 43 | defaultValue = "false", 44 | showDefaultValue = ALWAYS 45 | ) 46 | var noHeaders: Boolean = false 47 | 48 | @Option( 49 | names = ["-t", "--no-titles"], 50 | description = ["Disables table title using file name and sheet name (or just file name for .csv)"], 51 | defaultValue = "false", 52 | showDefaultValue = ALWAYS 53 | ) 54 | var noTitles: Boolean = false 55 | 56 | @Option( 57 | names = ["-s", "--sheet"], 58 | paramLabel = "2", 59 | description = ["Sheet number, starting at 1. if not provided, it will try to print all sheets for all files"], 60 | arity = "1" 61 | ) 62 | var sheetNumber: String = "all" 63 | 64 | override fun call(): Int { 65 | inputFiles.forEach { 66 | if (!it.exists()) throw ParameterException(out.commandLine(), "${it.name} does not exist") 67 | } 68 | 69 | inputFiles.forEach { 70 | if (it.extension !in allowedFileExtensions) throw ParameterException( 71 | out.commandLine(), 72 | "${it.name} needs to be of type ${allowedFileExtensions.joinToString()}" 73 | ) 74 | } 75 | 76 | inputFiles.forEach { file -> 77 | when (file.extension) { 78 | "xlsx" -> FileInputStream(file).use { 79 | 80 | val workBook = XSSFWorkbook(it) 81 | if (sheetNumber == "all") { 82 | workBook.forEach { sheet -> sheet.print(noHeaders, file.nameWithoutExtension) } 83 | } else { 84 | workBook.getSheetAt(sheetNumber.toInt() - 1).print(noHeaders, file.nameWithoutExtension) 85 | } 86 | } 87 | else -> with(file) { print() } 88 | } 89 | out.newLine() 90 | } 91 | return ExitCode.OK 92 | } 93 | 94 | private fun File.print() { 95 | val fileLines = readLines() 96 | if (fileLines.isNotEmpty()) { 97 | out.println("[${if (noHeaders) "" else "%header,"}format=csv,separator=;]") 98 | if (!noTitles) out.println(".${nameWithoutExtension}") 99 | out.println("|===") 100 | out.println(fileLines.joinToString(separator = lineSeparator())) 101 | out.println("|===") 102 | } 103 | } 104 | 105 | private fun Sheet.print(noHeaders: Boolean, fileName: String) { 106 | val maxOfFirstPhysicalCell = map { row -> row.firstCellNum.toInt() }.max() ?: 0 107 | val minOfFirstNonEmptyCell = map { row -> row.takeWhile { cell -> cell.isEmpty }.size }.min() ?: 0 108 | val emptyCellsToShift = maxOf(maxOfFirstPhysicalCell, minOfFirstNonEmptyCell) 109 | 110 | val rows = toList().takeLastWhile { row -> row.isNotEmpty } 111 | 112 | if (rows.isNotEmpty()) { 113 | if (noHeaders) { 114 | rows.printColumnDescriptor(emptyCellsToShift) 115 | tableSeparator(fileName) 116 | rows.printContent(emptyCellsToShift) 117 | } else { 118 | tableSeparator(fileName) 119 | rows.printHeader(emptyCellsToShift) 120 | rows.printContentAfterHeader(emptyCellsToShift) 121 | } 122 | out.println("|===") 123 | out.newLine() 124 | } 125 | } 126 | 127 | private fun List.printColumnDescriptor(emptyCellsToShift: Int) = 128 | out.println( 129 | """[cols="${ 130 | first().filterIndexed { index, cell -> cell.isNotEmpty || index >= emptyCellsToShift }.count() 131 | }*"]""" 132 | ) 133 | 134 | private fun Sheet.tableSeparator(fileName: String) = 135 | out.println(if (noTitles) "|===" else ".$fileName $sheetName${lineSeparator()}|===") 136 | 137 | private fun List.printHeader(emptyCellsToShift: Int) = 138 | out.println( 139 | first().cellIterator() 140 | .asSequence() 141 | .filterIndexed { index, cell -> cell.isNotEmpty || index >= emptyCellsToShift } 142 | .map(renderCell) 143 | .joinToString(prefix = "|", separator = " |") 144 | ) 145 | 146 | private fun List.printContentAfterHeader(emptyCellsToShift: Int) = 147 | out.println(drop(1).joinRows(emptyCellsToShift)) 148 | 149 | private fun List.printContent(emptyCellsToShift: Int) = 150 | out.println(joinRows(emptyCellsToShift)) 151 | 152 | private fun List.joinRows(emptyCellsToShift: Int) = 153 | joinToString(separator = lineSeparator() + lineSeparator()) { 154 | it.cellIterator() 155 | .asSequence() 156 | .filterIndexed { index, cell -> cell.isNotEmpty || index >= emptyCellsToShift } 157 | .map(renderCell) 158 | .joinToString(prefix = "|", separator = "${lineSeparator()}|") 159 | } 160 | 161 | } 162 | 163 | val renderCell: (Cell) -> String = { cell -> 164 | when (cell.cellType) { 165 | NUMERIC -> cell.numericCellValue.toString() 166 | STRING -> cell.stringCellValue 167 | FORMULA -> cell.cellFormula 168 | BOOLEAN -> cell.booleanCellValue.toString() 169 | else -> "" 170 | } 171 | } 172 | 173 | internal fun command(args: Array) = CommandLine(Excel2Asciidoc()).execute(*args) 174 | private fun CommandSpec.println(s: String) = commandLine().out.println(s) 175 | private fun CommandSpec.newLine() = commandLine().out.println(lineSeparator()) 176 | private val Cell.isEmpty get() = cellType == BLANK || renderCell(this).trim() == "" 177 | private val Cell.isNotEmpty get() = !isEmpty 178 | private val Row.isNotEmpty get() = cellIterator().asSequence().any { it.isNotEmpty } -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | quarkus.log.level=WARN 2 | quarkus.banner.enabled=false -------------------------------------------------------------------------------- /src/test/kotlin/fr/ncomet/MainTest.kt: -------------------------------------------------------------------------------- 1 | package fr.ncomet 2 | 3 | import com.ginsberg.junit.exit.ExpectSystemExitWithStatus 4 | import org.assertj.core.api.Assertions.assertThat 5 | import org.junit.jupiter.api.Test 6 | import org.junitpioneer.jupiter.StdIo 7 | import org.junitpioneer.jupiter.StdOut 8 | import java.lang.System.lineSeparator 9 | 10 | class MainTest { 11 | 12 | @Test 13 | @ExpectSystemExitWithStatus(2) 14 | fun `should exit(2) if file does not exists`() { 15 | main(arrayOf("src/test/resources/unknown.xlsx")) 16 | } 17 | 18 | @Test 19 | @ExpectSystemExitWithStatus(2) 20 | fun `should exit(2) if file extension is not allowed`() { 21 | main(arrayOf("src/test/resources/file.test")) 22 | } 23 | 24 | @Test 25 | fun `should load an xlsx file`() { 26 | command(arrayOf("src/test/resources/file.xlsx")) 27 | } 28 | 29 | @Test 30 | @StdIo 31 | fun `should produce expected output on an xlsx file`(out: StdOut) { 32 | command(arrayOf("src/test/resources/file.xlsx")) 33 | 34 | assertThat(out.capturedLines().joinToString(lineSeparator())).isEqualTo( 35 | """.file Sheet1 36 | :|=== 37 | :|First Name |Last Name |Gender |Country |Age |Date |Id |Number 38 | :|Dulce 39 | :|Abril 40 | :|Female 41 | :|United States 42 | :|32.0 43 | :|15/10/2017 44 | :|1562.0 45 | :|32.3 46 | : 47 | :|Mara 48 | :|Hashimoto 49 | :|Female 50 | :|Great Britain 51 | :|25.0 52 | :|16/08/2016 53 | :|1582.0 54 | :|23.0 55 | : 56 | :|Philip 57 | :|Gent 58 | :|Male 59 | :|France 60 | :|36.0 61 | :|21/05/2015 62 | :|2587.0 63 | :|15.5 64 | : 65 | :|Kathleen 66 | :|Hanner 67 | :|Female 68 | :|United States 69 | :|25.0 70 | :|15/10/2017 71 | :|3549.0 72 | :|23.5445 73 | : 74 | :|Nereida 75 | :|Magwood 76 | :|Female 77 | :|United States 78 | :|58.0 79 | :|16/08/2016 80 | :|2468.0 81 | :|11.0 82 | : 83 | :|Gaston 84 | :|Brumm 85 | :|Male 86 | :|United States 87 | :|24.0 88 | :|21/05/2015 89 | :|2554.0 90 | :|0.4455 91 | : 92 | :|Etta 93 | :|Hurn 94 | :|Female 95 | :|Great Britain 96 | :|56.0 97 | :|15/10/2017 98 | :|3598.0 99 | :|23.0 100 | : 101 | :|Earlean 102 | :|Melgar 103 | :|Female 104 | :|United States 105 | :|27.0 106 | :|16/08/2016 107 | :|2456.0 108 | :|14.0 109 | : 110 | :|Vincenza 111 | :|Weiland 112 | :|Female 113 | :|United States 114 | :|40.0 115 | :|21/05/2015 116 | :|6548.0 117 | :|6.0 118 | :|=== 119 | """.trimMarginAndWindowsCR() 120 | ) 121 | } 122 | 123 | @Test 124 | @StdIo 125 | fun `should produce expected output on a shifted xlsx file`(out: StdOut) { 126 | command(arrayOf("src/test/resources/file-shifted.xlsx")) 127 | 128 | assertThat(out.capturedLines().joinToString(lineSeparator())).isEqualTo( 129 | """.file-shifted Sheet1 130 | :|=== 131 | :|First Name |Last Name |Gender |Country |Age |Date |Id |Number 132 | :|Dulce 133 | :|Abril 134 | :|Female 135 | :|United States 136 | :|32.0 137 | :|15/10/2017 138 | :|1562.0 139 | :|32.3 140 | : 141 | :|Mara 142 | :|Hashimoto 143 | :|Female 144 | :|Great Britain 145 | :|25.0 146 | :|16/08/2016 147 | :|1582.0 148 | :|23.0 149 | : 150 | :|Philip 151 | :|Gent 152 | :|Male 153 | :|France 154 | :|36.0 155 | :|21/05/2015 156 | :|2587.0 157 | :|15.5 158 | : 159 | :|Kathleen 160 | :|Hanner 161 | :|Female 162 | :|United States 163 | :|25.0 164 | :|15/10/2017 165 | :|3549.0 166 | :|23.5445 167 | : 168 | :|Nereida 169 | :|Magwood 170 | :|Female 171 | :|United States 172 | :|58.0 173 | :|16/08/2016 174 | :|2468.0 175 | :|11.0 176 | : 177 | :|Gaston 178 | :|Brumm 179 | :|Male 180 | :|United States 181 | :|24.0 182 | :|21/05/2015 183 | :|2554.0 184 | :|0.4455 185 | : 186 | :|Etta 187 | :|Hurn 188 | :|Female 189 | :|Great Britain 190 | :|56.0 191 | :|15/10/2017 192 | :|3598.0 193 | :|23.0 194 | : 195 | :|Earlean 196 | :|Melgar 197 | :|Female 198 | :|United States 199 | :|27.0 200 | :|16/08/2016 201 | :|2456.0 202 | :|14.0 203 | : 204 | :|Vincenza 205 | :|Weiland 206 | :|Female 207 | :|United States 208 | :|40.0 209 | :|21/05/2015 210 | :|6548.0 211 | :|6.0 212 | :|=== 213 | """.trimMarginAndWindowsCR() 214 | ) 215 | } 216 | 217 | @Test 218 | @StdIo 219 | fun `should produce expected output on an xlsx file without header (-n option)`(out: StdOut) { 220 | command(arrayOf("src/test/resources/file.xlsx", "-n")) 221 | 222 | assertThat(out.capturedLines().joinToString(lineSeparator())).isEqualTo( 223 | """[cols="8*"] 224 | :.file Sheet1 225 | :|=== 226 | :|First Name 227 | :|Last Name 228 | :|Gender 229 | :|Country 230 | :|Age 231 | :|Date 232 | :|Id 233 | :|Number 234 | : 235 | :|Dulce 236 | :|Abril 237 | :|Female 238 | :|United States 239 | :|32.0 240 | :|15/10/2017 241 | :|1562.0 242 | :|32.3 243 | : 244 | :|Mara 245 | :|Hashimoto 246 | :|Female 247 | :|Great Britain 248 | :|25.0 249 | :|16/08/2016 250 | :|1582.0 251 | :|23.0 252 | : 253 | :|Philip 254 | :|Gent 255 | :|Male 256 | :|France 257 | :|36.0 258 | :|21/05/2015 259 | :|2587.0 260 | :|15.5 261 | : 262 | :|Kathleen 263 | :|Hanner 264 | :|Female 265 | :|United States 266 | :|25.0 267 | :|15/10/2017 268 | :|3549.0 269 | :|23.5445 270 | : 271 | :|Nereida 272 | :|Magwood 273 | :|Female 274 | :|United States 275 | :|58.0 276 | :|16/08/2016 277 | :|2468.0 278 | :|11.0 279 | : 280 | :|Gaston 281 | :|Brumm 282 | :|Male 283 | :|United States 284 | :|24.0 285 | :|21/05/2015 286 | :|2554.0 287 | :|0.4455 288 | : 289 | :|Etta 290 | :|Hurn 291 | :|Female 292 | :|Great Britain 293 | :|56.0 294 | :|15/10/2017 295 | :|3598.0 296 | :|23.0 297 | : 298 | :|Earlean 299 | :|Melgar 300 | :|Female 301 | :|United States 302 | :|27.0 303 | :|16/08/2016 304 | :|2456.0 305 | :|14.0 306 | : 307 | :|Vincenza 308 | :|Weiland 309 | :|Female 310 | :|United States 311 | :|40.0 312 | :|21/05/2015 313 | :|6548.0 314 | :|6.0 315 | :|=== 316 | """.trimMarginAndWindowsCR() 317 | ) 318 | } 319 | 320 | @Test 321 | @StdIo 322 | fun `should produce expected output on a shifted xlsx file without header (-n option)`(out: StdOut) { 323 | command(arrayOf("src/test/resources/file-shifted.xlsx", "-n")) 324 | 325 | assertThat(out.capturedLines().joinToString(lineSeparator())).isEqualTo( 326 | """[cols="8*"] 327 | :.file-shifted Sheet1 328 | :|=== 329 | :|First Name 330 | :|Last Name 331 | :|Gender 332 | :|Country 333 | :|Age 334 | :|Date 335 | :|Id 336 | :|Number 337 | : 338 | :|Dulce 339 | :|Abril 340 | :|Female 341 | :|United States 342 | :|32.0 343 | :|15/10/2017 344 | :|1562.0 345 | :|32.3 346 | : 347 | :|Mara 348 | :|Hashimoto 349 | :|Female 350 | :|Great Britain 351 | :|25.0 352 | :|16/08/2016 353 | :|1582.0 354 | :|23.0 355 | : 356 | :|Philip 357 | :|Gent 358 | :|Male 359 | :|France 360 | :|36.0 361 | :|21/05/2015 362 | :|2587.0 363 | :|15.5 364 | : 365 | :|Kathleen 366 | :|Hanner 367 | :|Female 368 | :|United States 369 | :|25.0 370 | :|15/10/2017 371 | :|3549.0 372 | :|23.5445 373 | : 374 | :|Nereida 375 | :|Magwood 376 | :|Female 377 | :|United States 378 | :|58.0 379 | :|16/08/2016 380 | :|2468.0 381 | :|11.0 382 | : 383 | :|Gaston 384 | :|Brumm 385 | :|Male 386 | :|United States 387 | :|24.0 388 | :|21/05/2015 389 | :|2554.0 390 | :|0.4455 391 | : 392 | :|Etta 393 | :|Hurn 394 | :|Female 395 | :|Great Britain 396 | :|56.0 397 | :|15/10/2017 398 | :|3598.0 399 | :|23.0 400 | : 401 | :|Earlean 402 | :|Melgar 403 | :|Female 404 | :|United States 405 | :|27.0 406 | :|16/08/2016 407 | :|2456.0 408 | :|14.0 409 | : 410 | :|Vincenza 411 | :|Weiland 412 | :|Female 413 | :|United States 414 | :|40.0 415 | :|21/05/2015 416 | :|6548.0 417 | :|6.0 418 | :|=== 419 | """.trimMarginAndWindowsCR() 420 | ) 421 | } 422 | 423 | @Test 424 | @StdIo 425 | fun `should produce expected output on an xlsx file with 3 sheets`(out: StdOut) { 426 | command(arrayOf("src/test/resources/file-3-sheets.xlsx")) 427 | 428 | assertThat(out.capturedLines().joinToString(lineSeparator())).isEqualTo( 429 | """.file-3-sheets Sheet1 430 | :|=== 431 | :|First Name |Last Name |Gender |Country |Age |Date |Id |Number 432 | :|Dulce 433 | :|Abril 434 | :|Female 435 | :|United States 436 | :|32.0 437 | :|15/10/2017 438 | :|1562.0 439 | :|32.3 440 | : 441 | :|Mara 442 | :|Hashimoto 443 | :|Female 444 | :|Great Britain 445 | :|25.0 446 | :|16/08/2016 447 | :|1582.0 448 | :|23.0 449 | : 450 | :|Philip 451 | :|Gent 452 | :|Male 453 | :|France 454 | :|36.0 455 | :|21/05/2015 456 | :|2587.0 457 | :|15.5 458 | :|=== 459 | : 460 | : 461 | :.file-3-sheets Sheet2 462 | :|=== 463 | :|Animal |Weight |Temperature 464 | :|Duck 465 | :|1.3 466 | :|180.0 467 | : 468 | :|Cow 469 | :|1250.0 470 | :|200.0 471 | : 472 | :|Lamb 473 | :|30.0 474 | :|175.0 475 | :|=== 476 | : 477 | : 478 | :.file-3-sheets Sheet3 479 | :|=== 480 | :|A |B |C |D |E 481 | :|1.0 482 | :|2.0 483 | :|3.0 484 | :|4.0 485 | :|5.0 486 | : 487 | :|6.0 488 | :|7.0 489 | :|8.0 490 | :|9.0 491 | :|10.0 492 | : 493 | :|11.0 494 | :|12.0 495 | :|13.0 496 | :|14.0 497 | :|15.0 498 | : 499 | :|16.0 500 | :|17.0 501 | :|18.0 502 | :|19.0 503 | :|20.0 504 | : 505 | :|21.0 506 | :|22.0 507 | :|23.0 508 | :|24.0 509 | :|25.0 510 | :|=== 511 | """.trimMarginAndWindowsCR() 512 | ) 513 | } 514 | 515 | @Test 516 | @StdIo 517 | fun `should produce expected output on a shifted xlsx file with 3 sheets`(out: StdOut) { 518 | command(arrayOf("src/test/resources/file-3-sheets-shifted.xlsx")) 519 | 520 | assertThat(out.capturedLines().joinToString(lineSeparator())).isEqualTo( 521 | """.file-3-sheets-shifted Sheet1 522 | :|=== 523 | :|First Name |Last Name |Gender |Country |Age |Date |Id |Number 524 | :|Dulce 525 | :|Abril 526 | :|Female 527 | :|United States 528 | :|32.0 529 | :|15/10/2017 530 | :|1562.0 531 | :|32.3 532 | : 533 | :|Mara 534 | :|Hashimoto 535 | :|Female 536 | :|Great Britain 537 | :|25.0 538 | :|16/08/2016 539 | :|1582.0 540 | :|23.0 541 | : 542 | :|Philip 543 | :|Gent 544 | :|Male 545 | :|France 546 | :|36.0 547 | :|21/05/2015 548 | :|2587.0 549 | :|15.5 550 | :|=== 551 | : 552 | : 553 | :.file-3-sheets-shifted Sheet2 554 | :|=== 555 | :|Animal |Weight |Temperature 556 | :|Duck 557 | :|1.3 558 | :|180.0 559 | : 560 | :|Cow 561 | :|1250.0 562 | :|200.0 563 | : 564 | :|Lamb 565 | :|30.0 566 | :|175.0 567 | :|=== 568 | : 569 | : 570 | :.file-3-sheets-shifted Sheet3 571 | :|=== 572 | :|A |B |C |D |E 573 | :|1.0 574 | :|2.0 575 | :|3.0 576 | :|4.0 577 | :|5.0 578 | : 579 | :|6.0 580 | :|7.0 581 | :|8.0 582 | :|9.0 583 | :|10.0 584 | : 585 | :|11.0 586 | :|12.0 587 | :|13.0 588 | :|14.0 589 | :|15.0 590 | : 591 | :|16.0 592 | :|17.0 593 | :|18.0 594 | :|19.0 595 | :|20.0 596 | : 597 | :|21.0 598 | :|22.0 599 | :|23.0 600 | :|24.0 601 | :|25.0 602 | :|=== 603 | """.trimMarginAndWindowsCR() 604 | ) 605 | } 606 | 607 | @Test 608 | @StdIo 609 | fun `should produce expected output on an xlsx file with 3 sheets with explicit sheet (-s option)`(out: StdOut) { 610 | command(arrayOf("src/test/resources/file-3-sheets.xlsx", "-s=2")) 611 | 612 | assertThat(out.capturedLines().joinToString(lineSeparator())).isEqualTo( 613 | """.file-3-sheets Sheet2 614 | :|=== 615 | :|Animal |Weight |Temperature 616 | :|Duck 617 | :|1.3 618 | :|180.0 619 | : 620 | :|Cow 621 | :|1250.0 622 | :|200.0 623 | : 624 | :|Lamb 625 | :|30.0 626 | :|175.0 627 | :|=== 628 | """.trimMarginAndWindowsCR() 629 | ) 630 | } 631 | 632 | @Test 633 | @StdIo 634 | fun `should produce expected output without titles (-t option)`(out: StdOut) { 635 | command(arrayOf("src/test/resources/file-3-sheets.xlsx", "-s=2", "-t")) 636 | 637 | assertThat(out.capturedLines().joinToString(lineSeparator())).isEqualTo( 638 | """|=== 639 | :|Animal |Weight |Temperature 640 | :|Duck 641 | :|1.3 642 | :|180.0 643 | : 644 | :|Cow 645 | :|1250.0 646 | :|200.0 647 | : 648 | :|Lamb 649 | :|30.0 650 | :|175.0 651 | :|=== 652 | """.trimMarginAndWindowsCR() 653 | ) 654 | } 655 | 656 | @Test 657 | @StdIo 658 | fun `should produce expected output on a shifted xlsx file with 3 sheets with explicit sheet (-s option)`(out: StdOut) { 659 | command(arrayOf("src/test/resources/file-3-sheets-shifted.xlsx", "-s=2")) 660 | 661 | assertThat(out.capturedLines().joinToString(lineSeparator())).isEqualTo( 662 | """.file-3-sheets-shifted Sheet2 663 | :|=== 664 | :|Animal |Weight |Temperature 665 | :|Duck 666 | :|1.3 667 | :|180.0 668 | : 669 | :|Cow 670 | :|1250.0 671 | :|200.0 672 | : 673 | :|Lamb 674 | :|30.0 675 | :|175.0 676 | :|=== 677 | """.trimMarginAndWindowsCR() 678 | ) 679 | } 680 | 681 | @Test 682 | @StdIo 683 | fun `should print empty output for an empty xlsx file`(out: StdOut) { 684 | command(arrayOf("src/test/resources/empty-file.xlsx")) 685 | 686 | assertThat(out.capturedLines().joinToString(lineSeparator())).isEqualTo("") 687 | } 688 | 689 | @Test 690 | @StdIo 691 | fun `should product output for every cell type`(out: StdOut) { 692 | command(arrayOf("src/test/resources/file-every-cell-types.xlsx")) 693 | 694 | assertThat(out.capturedLines().joinToString(lineSeparator())).isEqualTo( 695 | """.file-every-cell-types Feuille1 696 | :|=== 697 | :|String |1.0 |1.65 |SUM(B1,C1) |wtf() |1/0 |true 698 | : 699 | :|=== 700 | """.trimMarginAndWindowsCR() 701 | ) 702 | } 703 | 704 | @Test 705 | @StdIo 706 | fun `should process a csv file`(out: StdOut) { 707 | command(arrayOf("src/test/resources/file.csv")) 708 | 709 | assertThat(out.capturedLines().joinToString(lineSeparator())).isEqualTo( 710 | """[%header,format=csv,separator=;] 711 | :.file 712 | :|=== 713 | :First Name;Last Name;Gender;Country;Age;Date;Id;Number 714 | :Dulce;Abril;Female;United States;32;15/10/2017;1562;32 715 | :Mara;Hashimoto;Female;Great Britain;25;16/08/2016;1582;23 716 | :Philip;Gent;Male;France;36;21/05/2015;2587;16 717 | :Kathleen;Hanner;Female;United States;25;15/10/2017;3549;24 718 | :Nereida;Magwood;Female;United States;58;16/08/2016;2468;11 719 | :Gaston;Brumm;Male;United States;24;21/05/2015;2554;0 720 | :Etta;Hurn;Female;Great Britain;56;15/10/2017;3598;23 721 | :Earlean;Melgar;Female;United States;27;16/08/2016;2456;14 722 | :Vincenza;Weiland;Female;United States;40;21/05/2015;6548;6 723 | :|=== 724 | """.trimMarginAndWindowsCR() 725 | ) 726 | } 727 | 728 | @Test 729 | @StdIo 730 | fun `should process a csv file without header (-n option)`(out: StdOut) { 731 | command(arrayOf("src/test/resources/file.csv", "-n")) 732 | 733 | assertThat(out.capturedLines().joinToString(lineSeparator())).isEqualTo( 734 | """[format=csv,separator=;] 735 | :.file 736 | :|=== 737 | :First Name;Last Name;Gender;Country;Age;Date;Id;Number 738 | :Dulce;Abril;Female;United States;32;15/10/2017;1562;32 739 | :Mara;Hashimoto;Female;Great Britain;25;16/08/2016;1582;23 740 | :Philip;Gent;Male;France;36;21/05/2015;2587;16 741 | :Kathleen;Hanner;Female;United States;25;15/10/2017;3549;24 742 | :Nereida;Magwood;Female;United States;58;16/08/2016;2468;11 743 | :Gaston;Brumm;Male;United States;24;21/05/2015;2554;0 744 | :Etta;Hurn;Female;Great Britain;56;15/10/2017;3598;23 745 | :Earlean;Melgar;Female;United States;27;16/08/2016;2456;14 746 | :Vincenza;Weiland;Female;United States;40;21/05/2015;6548;6 747 | :|=== 748 | """.trimMarginAndWindowsCR() 749 | ) 750 | } 751 | 752 | @Test 753 | @StdIo 754 | fun `should process a csv file without titles (-t option)`(out: StdOut) { 755 | command(arrayOf("src/test/resources/file.csv", "-t")) 756 | 757 | assertThat(out.capturedLines().joinToString(lineSeparator())).isEqualTo( 758 | """[%header,format=csv,separator=;] 759 | :|=== 760 | :First Name;Last Name;Gender;Country;Age;Date;Id;Number 761 | :Dulce;Abril;Female;United States;32;15/10/2017;1562;32 762 | :Mara;Hashimoto;Female;Great Britain;25;16/08/2016;1582;23 763 | :Philip;Gent;Male;France;36;21/05/2015;2587;16 764 | :Kathleen;Hanner;Female;United States;25;15/10/2017;3549;24 765 | :Nereida;Magwood;Female;United States;58;16/08/2016;2468;11 766 | :Gaston;Brumm;Male;United States;24;21/05/2015;2554;0 767 | :Etta;Hurn;Female;Great Britain;56;15/10/2017;3598;23 768 | :Earlean;Melgar;Female;United States;27;16/08/2016;2456;14 769 | :Vincenza;Weiland;Female;United States;40;21/05/2015;6548;6 770 | :|=== 771 | """.trimMarginAndWindowsCR() 772 | ) 773 | } 774 | 775 | @Test 776 | @StdIo 777 | fun `should print empty output for an empty csv file`(out: StdOut) { 778 | command(arrayOf("src/test/resources/empty-file.csv")) 779 | 780 | assertThat(out.capturedLines().joinToString(lineSeparator())).isEqualTo("") 781 | } 782 | 783 | @Test 784 | @StdIo 785 | fun `should print two files`(out: StdOut) { 786 | command(arrayOf("src/test/resources/file.csv", "src/test/resources/file-3-sheets.xlsx")) 787 | 788 | assertThat(out.capturedLines().joinToString(lineSeparator())).isEqualTo( 789 | """[%header,format=csv,separator=;] 790 | :.file 791 | :|=== 792 | :First Name;Last Name;Gender;Country;Age;Date;Id;Number 793 | :Dulce;Abril;Female;United States;32;15/10/2017;1562;32 794 | :Mara;Hashimoto;Female;Great Britain;25;16/08/2016;1582;23 795 | :Philip;Gent;Male;France;36;21/05/2015;2587;16 796 | :Kathleen;Hanner;Female;United States;25;15/10/2017;3549;24 797 | :Nereida;Magwood;Female;United States;58;16/08/2016;2468;11 798 | :Gaston;Brumm;Male;United States;24;21/05/2015;2554;0 799 | :Etta;Hurn;Female;Great Britain;56;15/10/2017;3598;23 800 | :Earlean;Melgar;Female;United States;27;16/08/2016;2456;14 801 | :Vincenza;Weiland;Female;United States;40;21/05/2015;6548;6 802 | :|=== 803 | : 804 | : 805 | :.file-3-sheets Sheet1 806 | :|=== 807 | :|First Name |Last Name |Gender |Country |Age |Date |Id |Number 808 | :|Dulce 809 | :|Abril 810 | :|Female 811 | :|United States 812 | :|32.0 813 | :|15/10/2017 814 | :|1562.0 815 | :|32.3 816 | : 817 | :|Mara 818 | :|Hashimoto 819 | :|Female 820 | :|Great Britain 821 | :|25.0 822 | :|16/08/2016 823 | :|1582.0 824 | :|23.0 825 | : 826 | :|Philip 827 | :|Gent 828 | :|Male 829 | :|France 830 | :|36.0 831 | :|21/05/2015 832 | :|2587.0 833 | :|15.5 834 | :|=== 835 | : 836 | : 837 | :.file-3-sheets Sheet2 838 | :|=== 839 | :|Animal |Weight |Temperature 840 | :|Duck 841 | :|1.3 842 | :|180.0 843 | : 844 | :|Cow 845 | :|1250.0 846 | :|200.0 847 | : 848 | :|Lamb 849 | :|30.0 850 | :|175.0 851 | :|=== 852 | : 853 | : 854 | :.file-3-sheets Sheet3 855 | :|=== 856 | :|A |B |C |D |E 857 | :|1.0 858 | :|2.0 859 | :|3.0 860 | :|4.0 861 | :|5.0 862 | : 863 | :|6.0 864 | :|7.0 865 | :|8.0 866 | :|9.0 867 | :|10.0 868 | : 869 | :|11.0 870 | :|12.0 871 | :|13.0 872 | :|14.0 873 | :|15.0 874 | : 875 | :|16.0 876 | :|17.0 877 | :|18.0 878 | :|19.0 879 | :|20.0 880 | : 881 | :|21.0 882 | :|22.0 883 | :|23.0 884 | :|24.0 885 | :|25.0 886 | :|=== 887 | """.trimMarginAndWindowsCR() 888 | ) 889 | } 890 | } 891 | 892 | fun String.trimMarginAndWindowsCR() = trimMargin(":").replace("\n", lineSeparator()) -------------------------------------------------------------------------------- /src/test/resources/empty-file.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncomet/excel2adoc/6d164f047d91f418b6eeb19d877103707ec39a82/src/test/resources/empty-file.csv -------------------------------------------------------------------------------- /src/test/resources/empty-file.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncomet/excel2adoc/6d164f047d91f418b6eeb19d877103707ec39a82/src/test/resources/empty-file.xlsx -------------------------------------------------------------------------------- /src/test/resources/file-3-sheets-shifted.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncomet/excel2adoc/6d164f047d91f418b6eeb19d877103707ec39a82/src/test/resources/file-3-sheets-shifted.xlsx -------------------------------------------------------------------------------- /src/test/resources/file-3-sheets.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncomet/excel2adoc/6d164f047d91f418b6eeb19d877103707ec39a82/src/test/resources/file-3-sheets.xlsx -------------------------------------------------------------------------------- /src/test/resources/file-every-cell-types.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncomet/excel2adoc/6d164f047d91f418b6eeb19d877103707ec39a82/src/test/resources/file-every-cell-types.xlsx -------------------------------------------------------------------------------- /src/test/resources/file-shifted.csv: -------------------------------------------------------------------------------- 1 | ;;;;;;;; 2 | ;First Name;Last Name;Gender;Country;Age;Date;Id;Number 3 | ;Dulce;Abril;Female;United States;32;15/10/2017;1562;32 4 | ;Mara;Hashimoto;Female;Great Britain;25;16/08/2016;1582;23 5 | ;Philip;Gent;Male;France;36;21/05/2015;2587;16 6 | ;Kathleen;Hanner;Female;United States;25;15/10/2017;3549;24 7 | ;Nereida;Magwood;Female;United States;58;16/08/2016;2468;11 8 | ;Gaston;Brumm;Male;United States;24;21/05/2015;2554;0 9 | ;Etta;Hurn;Female;Great Britain;56;15/10/2017;3598;23 10 | ;Earlean;Melgar;Female;United States;27;16/08/2016;2456;14 11 | ;Vincenza;Weiland;Female;United States;40;21/05/2015;6548;6 -------------------------------------------------------------------------------- /src/test/resources/file-shifted.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncomet/excel2adoc/6d164f047d91f418b6eeb19d877103707ec39a82/src/test/resources/file-shifted.xlsx -------------------------------------------------------------------------------- /src/test/resources/file.adoc: -------------------------------------------------------------------------------- 1 | |=== 2 | |Header 1 |Header 2 |Header 3 |Header 4 3 | 4 | |Column 1, row 1 5 | |Column 2, row 1 6 | |Column 3, row 1 7 | |Column 4, row 1 8 | 9 | |Column 1, row 2 10 | |Column 2, row 2 11 | |Column 3, row 2 12 | |Column 4, row 2 13 | 14 | |Column 1, row 3 15 | |Column 2, row 3 16 | |Column 3, row 3 17 | |Column 4, row 3 18 | |=== 19 | 20 | [cols="4*"] 21 | |=== 22 | |Column 1, row 1 23 | |Column 2, row 1 24 | |Column 3, row 1 25 | |Column 4, row 1 26 | 27 | |Column 1, row 2 28 | |Column 2, row 2 29 | |Column 3, row 2 30 | |Column 4, row 2 31 | 32 | |Column 1, row 3 33 | |Column 2, row 3 34 | |Column 3, row 3 35 | |Column 4, row 3 36 | |=== 37 | 38 | [%header,format=csv,separator=;] 39 | |=== 40 | First Name;Last Name;Gender;Country;Age;Date;Id;Number 41 | Dulce;Abril;Female;United States;32;15/10/2017;1562;32 42 | Mara;Hashimoto;Female;Great Britain;25;16/08/2016;1582;23 43 | Philip;Gent;Male;France;36;21/05/2015;2587;16 44 | Kathleen;Hanner;Female;United States;25;15/10/2017;3549;24 45 | Nereida;Magwood;Female;United States;58;16/08/2016;2468;11 46 | Gaston;Brumm;Male;United States;24;21/05/2015;2554;0 47 | Etta;Hurn;Female;Great Britain;56;15/10/2017;3598;23 48 | Earlean;Melgar;Female;United States;27;16/08/2016;2456;14 49 | Vincenza;Weiland;Female;United States;40;21/05/2015;6548;6 50 | |=== 51 | 52 | [format=csv,separator=;] 53 | |=== 54 | Dulce;Abril;Female;United States;32;15/10/2017;1562;32 55 | Mara;Hashimoto;Female;Great Britain;25;16/08/2016;1582;23 56 | Philip;Gent;Male;France;36;21/05/2015;2587;16 57 | Kathleen;Hanner;Female;United States;25;15/10/2017;3549;24 58 | Nereida;Magwood;Female;United States;58;16/08/2016;2468;11 59 | Gaston;Brumm;Male;United States;24;21/05/2015;2554;0 60 | Etta;Hurn;Female;Great Britain;56;15/10/2017;3598;23 61 | Earlean;Melgar;Female;United States;27;16/08/2016;2456;14 62 | Vincenza;Weiland;Female;United States;40;21/05/2015;6548;6 63 | |=== 64 | -------------------------------------------------------------------------------- /src/test/resources/file.csv: -------------------------------------------------------------------------------- 1 | First Name;Last Name;Gender;Country;Age;Date;Id;Number 2 | Dulce;Abril;Female;United States;32;15/10/2017;1562;32 3 | Mara;Hashimoto;Female;Great Britain;25;16/08/2016;1582;23 4 | Philip;Gent;Male;France;36;21/05/2015;2587;16 5 | Kathleen;Hanner;Female;United States;25;15/10/2017;3549;24 6 | Nereida;Magwood;Female;United States;58;16/08/2016;2468;11 7 | Gaston;Brumm;Male;United States;24;21/05/2015;2554;0 8 | Etta;Hurn;Female;Great Britain;56;15/10/2017;3598;23 9 | Earlean;Melgar;Female;United States;27;16/08/2016;2456;14 10 | Vincenza;Weiland;Female;United States;40;21/05/2015;6548;6 -------------------------------------------------------------------------------- /src/test/resources/file.test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncomet/excel2adoc/6d164f047d91f418b6eeb19d877103707ec39a82/src/test/resources/file.test -------------------------------------------------------------------------------- /src/test/resources/file.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncomet/excel2adoc/6d164f047d91f418b6eeb19d877103707ec39a82/src/test/resources/file.xlsx --------------------------------------------------------------------------------