All Downloads are FREE. Search and download functionalities are using the official Maven repository.

kz.greetgo.msoffice.util.UtilOffice Maven / Gradle / Ivy

There is a newer version: 0.5.9
Show newest version
package kz.greetgo.msoffice.util;

import kz.greetgo.msoffice.LeftFileException;

import java.awt.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class UtilOffice {
  /**
   * Стандартное представление даты и времени по w3c
   */
  @SuppressWarnings("SpellCheckingInspection")
  public static final SimpleDateFormat W3CDTF = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");

  /**
   * Количество миллисекунд в сутках
   */
  public static final int MILLIS_IN_DAY = 24 * 60 * 60 * 1000;

  /**
   * Преобразует дату в формат W3CDTF
   *
   * @param date исходная дата
   * @return строка даты в формате W3CDTF, или пустая строка если на вход пришел null
   */
  @SuppressWarnings("SpellCheckingInspection")
  public static String toW3CDTF(Date date) {
    if (date == null) return null;
    return W3CDTF.format(date);
  }

  /**
   * Преобразует строку формата W3CDTF в дату
   *
   * @param str строка содержащая дату в формате W3CDTF
   * @return дата или null, если str == null
   */
  @SuppressWarnings("SpellCheckingInspection")
  public static Date parseW3CDTF(String str) {
    if (str == null) return null;
    try {
      return W3CDTF.parse(str);
    } catch (ParseException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * Увеличивает длину строки до указанной добавлением нуля в начало строки
   *
   * @param len требуемая длина строки
   * @param s   исходная строка
   * @return результирующая строка
   */
  public static String toLenZero(int len, String s) {
    StringBuilder sb = new StringBuilder();
    if (s != null) sb.append(s);
    while (len > sb.length()) {
      sb.insert(0, ' ');
    }
    return sb.toString();
  }

  /**
   * Представляет цвет в виде шеснадцатиричной строки
   *
   * @param color исходный цвет
   * @return шеснадцатиричное представление цвета
   */
  public static String toHEX(Color color) {
    if (color == null) return "";
    return toLenZero(2, Integer.toHexString(color.getRed()).toUpperCase())
      + toLenZero(2, Integer.toHexString(color.getGreen()).toUpperCase())
      + toLenZero(2, Integer.toHexString(color.getBlue()).toUpperCase());
  }

  public static void appendToSB(InputStream in, StringBuilder sb) {
    try {
      appendToSB0(in, sb);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  public static void appendToSB0(InputStream in, StringBuilder sb) throws Exception {
    BufferedReader br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
    String line;
    while ((line = br.readLine()) != null) {
      sb.append(line);
      sb.append(System.getProperty("line.separator"));
    }
    br.close();
  }

  /**
   * Принимает поток как текстовый в кодировке UTF-8, и представляет его как строку
   *
   * @param in принимаемый поток. Будет считан до конца и закрыт.
   * @return полученная строка
   */
  public static String streamToStr(InputStream in) {
    StringBuilder sb = new StringBuilder();
    appendToSB(in, sb);
    return sb.toString();
  }

  @SuppressWarnings("unused")
  public static String streamToStr0(InputStream in) throws Exception {
    StringBuilder sb = new StringBuilder();
    appendToSB0(in, sb);
    return sb.toString();
  }

  public static void copyStreams(InputStream in, OutputStream out, int bufferSize)
    throws IOException {
    byte[] buffer = new byte[bufferSize];
    int readBytes;
    while ((readBytes = in.read(buffer)) != -1) {
      out.write(buffer, 0, readBytes);
    }
  }

  /**
   * Копирует данные из входного потока в выходной через буфер размером 2048 байт
   *
   * @param in  входной поток
   * @param out выходной поток
   * @throws IOException происходт в случае ошибки ввода/вывода
   */
  public static void copyStreams(InputStream in, OutputStream out) throws IOException {
    copyStreams(in, out, 2048);
  }

  /**
   * Удаляет слэш из начала строки, если он там есть, иначе ни чего не делает
   *
   * @param s исходная строка
   * @return результирующая строка
   */
  public static String killFirstSlash(String s) {
    if (s == null) return null;
    if (!s.startsWith("/")) return s;
    return s.substring(1);
  }

  /**
   * 

* Вырезает из полного пути с именем файла только его имя. Если в конце слэш, то он игнорируется *

*

* Например: *

* * asd/asd/wow.xml -> wow.xml
* /wow/asd/dsa/uu/mama/ -> mama *
* * @param fullName полный путь к файлу или папке * @return только имя файла или папки */ public static String extractBaseName(String fullName) { if (fullName.endsWith("/")) { fullName = fullName.substring(0, fullName.length() - 1); } int index = fullName.lastIndexOf('/'); if (index < 0) return fullName; return fullName.substring(index + 1); } /** * Удаляет папку вместе со всем её содержимым * * @param dir путь к удаляемой папке (абсолютный или относительный) * @return признак произведения операции: если файловая система не изменилась, то возвращается * лож; если же хоть что-то удалилось, то возвращается истина */ public static boolean removeDir(String dir) { cleanDir(dir); return new File(dir).delete(); } /** * Очищает папку - удаляет все её файлы и подпапки * * @param dir путь к очищаемой папке (абсолютный или относительный) * @return признак произведения операции: если файловая система не изменилась, то возвращается * лож; если же хоть что-то удалилось, то возвращается истина */ @SuppressWarnings("UnusedReturnValue") public static boolean cleanDir(String dir) { String[] subNames = new File(dir).list(); if (subNames == null) return false; boolean ret = false; for (String name : subNames) { if (".".equals(name)) continue; if ("..".equals(name)) continue; File f = new File(dir + System.getProperty("file.separator") + name); if (f.isFile()) { boolean q = f.delete(); //ни в коем случае нельзя сокращать переменную q ret = ret || q; continue; } if (f.isDirectory()) { boolean q = removeDir(f.getPath()); //ни в коем случае нельзя сокращать переменную q ret = ret || q; continue; } throw new LeftFileException("Left file " + f); } return ret; } private static final String[] LETTER_BASE = new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}; /** * Формирует "буквенное" число: 0->A, 1->B, ..., 25->Z, 26->AA, 27->AB, .... (Такие числа * используются для обозначения колонок в электронных таблицах) * * @param n исходное число (должно быть больше или равно нулю) * @return результирующее "буквенное" число */ public static String toLettersNumber(int n) { StringBuilder ret = new StringBuilder(); appendLettersNumber(ret, n); return ret.toString(); } public static void appendLettersNumber(StringBuilder sb, int n) { if (n < 0) throw new IllegalArgumentException("n must be >= 0"); int base = LETTER_BASE.length; sb.append(LETTER_BASE[n % base]); n = n / base; while (n > 0) { sb.insert(0, LETTER_BASE[(n - 1) % base]); n = n / (base + 1); } } /** * Парсит буквенное число, преобразуя его в обычное: A->0, B->1, C->2, ..., Z->25, AA->26, AB->27, * ..., ZZ->701, AAA->702, ... (Такие числа используются для обозначения колонок в электронных * таблицах) * * @param s "буквенное" число * @return Распарсеное число */ public static int parseLettersNumber(String s) { if (s == null) { throw new NullPointerException("parseLettersNumber cannot parse null string"); } s = s.toUpperCase(); if (s.length() == 0) { throw new IllegalArgumentException("parseLettersNumber cannot parse empty string"); } int ret = s.charAt(0) - 'A'; for (int i = 1, C = s.length(); i < C; i++) { int current = s.charAt(i) - 'A'; ret = 26 * (ret + 1) + current; } return ret; } /** * Парсит представление координат ячейки. * * @param coordinate Строка с координатой: символьное обозначение столбца и номер строки ("B6", "C8", "AB12"). * @return [ col, row ], нумерация с 1 */ public static int[] parseCellCoordinate(String coordinate) { if (coordinate == null) throw new NullPointerException("Координата не должна быть пустой"); coordinate = coordinate.trim(); if (coordinate.length() < 1) throw new IllegalArgumentException("Координата не должна быть пустой"); int[] coordinateInt = new int[2]; coordinate = coordinate.toUpperCase(); int i = 0; while (i < coordinate.length()) { if (Character.isDigit(coordinate.charAt(i))) break; i++; } String col = coordinate.substring(0, i); String row = "0"; if (i < coordinate.length()) row = coordinate.substring(i); coordinateInt[0] = parseLettersNumber(col) + 1; coordinateInt[1] = Integer.parseInt(row); return coordinateInt; } /** *

* Формирует копию InputStream *

*

* Необходим например для предотвращения закрытия оригинального потока, при закрытии копии *

* * @param in оригинальный поток * @return копия */ public static InputStream copy(final InputStream in) { return new InputStream() { @Override public int read() throws IOException { return in.read(); } @Override public int read(byte[] b, int off, int len) throws IOException { return in.read(b, off, len); } }; } /** *

* Магическое число для преобразования excel-евского представления даты в java-кое представление * (и обратно) *

*

*

* это магическое число выведено подбором *

*/ private static final int EXCEL_DATE_MAGIC = 70 * 365 + 50; public static Calendar epochStart() { Calendar c = new GregorianCalendar(); c.set(Calendar.YEAR, 1970); c.set(Calendar.MONTH, 1); c.set(Calendar.DAY_OF_MONTH, 1); c.set(Calendar.HOUR_OF_DAY, 0); c.set(Calendar.MINUTE, 0); c.set(Calendar.SECOND, 0); c.set(Calendar.MILLISECOND, 0); return c; } /** * Преобразует excel-евское представление даты-времени в java-представление (java.util.Date) * * @param excelValue excel-евское представление даты-времени * @return java-представление даты-времени */ public static Date excelToDate(String excelValue) { if (excelValue == null || excelValue.trim().length() == 0) return null; Calendar c = epochStart(); BigDecimal value = new BigDecimal(excelValue); c.add(Calendar.DAY_OF_YEAR, value.setScale(0, RoundingMode.DOWN).intValueExact() - EXCEL_DATE_MAGIC); BigDecimal afterZero = value.subtract(value.setScale(0, RoundingMode.DOWN)); BigDecimal millis = afterZero.multiply(new BigDecimal(MILLIS_IN_DAY)); millis = millis.setScale(0, RoundingMode.HALF_UP); return new Date(c.getTimeInMillis() + millis.longValueExact()); } /** * Пребразует java-представление даты-времени в excel-евское * * @param date java-представление даты-времени * @return excel-евское представление даты-времени в виде строки */ public static String toExcelDateTime(Date date) { if (date == null) return null; Calendar c = epochStart(); long totalMillis = date.getTime() - c.getTimeInMillis(); int days = (int) (totalMillis / MILLIS_IN_DAY) + EXCEL_DATE_MAGIC; c.add(Calendar.DAY_OF_YEAR, days - EXCEL_DATE_MAGIC); int millis = (int) (date.getTime() - c.getTimeInMillis()); BigDecimal afterZero = new BigDecimal(millis).divide(new BigDecimal(MILLIS_IN_DAY), MathContext.DECIMAL64); BigDecimal bdDays = new BigDecimal(days); BigDecimal result = bdDays.add(afterZero); return result.toString(); } /** *

* Получает величину 16-чного символа *

*

* (0->0, 1->1, ..., 9->9, A->10, B->11, ..., F->15) *

* * @param c 16-чный символ * @return его величина */ public static int charAsHex(char c) { if ('0' <= c && c <= '9') return c - '0'; if ('A' <= c && c <= 'F') return c - 'A' + 10; if ('a' <= c && c <= 'f') return c - 'a' + 10; throw new IllegalArgumentException("Unknown hex digit " + c + " (code is " + (int) c + ")"); } /** * Парсит строку как целое представленое в 16-чных цыфрах * * @param hex входная строка * @param index индекс первого читаемого символа * @param count количество читаемых символов * @return полученое целое */ public static int parsePartAsHex(String hex, int index, int count) { int ret = 0; int base = 1; for (; count-- > 0; ) { ret += base * charAsHex(hex.charAt(index + count)); base *= 16; } return ret; } /** *

* Преобразует координаты ячейки таблицы в электронно-табличную форму *

*

* Например для
* (row,col) = (1,0) -> "A1"
* (row,col) = (4,1) -> "A4"
* (row,col) = (4,2) -> "B4"
* (row,col) = (7,3) -> "C7"
* (row,col) = (7,10) -> "J7"
*

* * @param row индекс строки (1 - первая строка, 2 - вторая, ...) * @param col индекс колонки (0 - первая колонка, 1 - вторая, ...) * @return электронно-табличная форма координат */ public static String toTablePosition(int row, int col) { return toLettersNumber(col) + row; } /** * Зиппует указанную папку со всем её содержимым рекурсивно и отправляет в указанный поток * * @param dir зиппуемая папка * @param out выводимый поток */ public static void zipDir(String dir, OutputStream out) { try { zipDirEx(dir, out); } catch (Exception e) { if (e instanceof RuntimeException) { throw (RuntimeException) e; } throw new RuntimeException(e); } } /** * Зиппует указанную папку со всем её содержимым рекурсивно и отправляет в указанный поток * * @param dir зиппуемая папка * @param out выводимый поток * @throws Exception утобы не делать try/catch-блок */ public static void zipDirEx(String dir, OutputStream out) throws Exception { final ZipOutputStream zOut; if (out instanceof ZipOutputStream) { zOut = (ZipOutputStream) out; } else { zOut = new ZipOutputStream(out); } appendDir(dir, "", zOut); zOut.close(); } private static void appendDir(String dir, String localPath, ZipOutputStream zOut) throws Exception { String[] list = new File(dir).list(); if (list != null) for (String localName : list) { String fullName = dir + "/" + localName; String localFullName = localName; if (localPath.length() > 0) { localFullName = localPath + "/" + localName; } if (new File(fullName).isDirectory()) { appendDir(fullName, localFullName, zOut); } else { appendFile(fullName, localFullName, zOut); } } } private static void appendFile(String fullName, String localFullName, ZipOutputStream zOut) throws Exception { zOut.putNextEntry(new ZipEntry(localFullName)); FileInputStream in = new FileInputStream(fullName); UtilOffice.copyStreams(in, zOut); in.close(); zOut.closeEntry(); } public static Integer strToInt(String str) { if (str == null) return null; return Integer.valueOf(str); } public static BigDecimal strToBd(String str) { if (str == null || str.trim().length() == 0) return null; return new BigDecimal(str.replace(',', '.')); } public static int strToIntOr(String str, int defaultValue) { Integer ret = strToInt(str); return ret != null ? ret : defaultValue; } @SafeVarargs public static T fnn(T... ttt) { for (T t : ttt) { if (t != null) return t; } return null; } public static boolean isFormatForDate(String format) { if (format == null) return false; format = format.trim().toLowerCase(); return format.contains("mm") || format.contains("yy") || format.contains("dd") || format.contains("hh") || format.contains("ss"); } public static String toLenLeft(int len, String str, String space) { StringBuilder sb = new StringBuilder(); sb.append(str); while (sb.length() < len) sb.insert(0, space); return sb.toString(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy