2017년 1월 16일 월요일

파워포인트 파워목업(powerMockup) - 화면설계를 쉽고 빠르게 하는 방법


안녕하세요,

평소 파워포인트를 많이 사용하시는 분이라면 아래 소개해드리는 프로그램을 이용하면 쉽고 빠르게 파워포인트 작업을 할 수 있습니다. 물론 퀄리티도 꽤 이쁘게 나옵니다.

저는 웹어플리케이션 개발자로 저만의 홈페이지를 만들어 보고자 화면설계를 시작하는데 평소 파워포인트를 사용하지 않다가 화면을 설계해보려고 하니 막막하기만 했었는데 파워목업의 도움을 받으니 파워포인트 비 전문가여도 제 생각을 정리하기가 수월해 졌습니다.




사용방법은 간단합니다. 
아래그림과 같이 우측에 있는 예제중에서 사용하고자 하는 아이템을 드레그하여 원하는 위치에 올려 놓기만 하면 됩니다.
그 다음 크기나 내용을 마음대로 커스텀마이징 할 수 있어서 굉장히 편하게 작업할 수 있습니다.


추가로 아래 그림과 같이 화면을 설명하는데 굉장히 유익한 아이콘들도 꽤 있습니다. 
저런아이콘이 없다면 실제로 저런 이펙트를 주기위해서 꽤나 고민이 많이 필요한데 말이죠




 아래 그림처럼 간단히 자신의 의도를 표현할 수 있습니다. 또 각각 아이탬마다 커스텀이 옵션으로 떠서 쉽게 바꿀수 있어요


안드로이드와 아이폰용 도구도 있어서 웹 뿐만아라 모바일앱을 만들고자 하는 스타트업에게는 필수 일것같습니다.



사용방법은 먼저 트라이얼을 다운받아 설치한다음, 파워포인트를 실행하기만 하면 위 그림들처럼 우측에 아이콘이 나오고 바로 사용할 수 있습니다.

단. 모든 아이콘을 사용할 수 는 없고 라이센스가 있습니다. 비용은 1유저에 59달러인데 파워목업을 사용하고 블로그에 이를 소개하는 글을 올린다음 아래주소에 요청하면 하루만에 무료 라이센스가 나온다고 합니다. 
조금만 고생해서 무료 라이센스로 쉽게 파워포인트 작업하세요~!


2014년 3월 11일 화요일

Spring AbstractExcelView를 이용한 엑셀파일 생성 및 다운로드(Spring + Jakarta POI)

  • 130903

#AbstractExcelView를 이용한 엑셀파일 생성 및 다운로드

엑셀파일 뷰를 생성하는방법으로 여러가지 방법이 있지만, 여기서는 컨트롤러의 메서드에서 String 타입의 뷰 이름을 리턴하고, BeanNameViewResolver를 사용하여 뷰를 생성하는 방법으로 구현하였다. 

#스프링 설정파일 dispatcher-servlet.xml
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
                    p:prefix="/WEB-INF/view/"
                    p:suffix=".jsp"
                    p:order="2"/>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" p:order="1"/>
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
             <property name="order" value="0"/>
             <property name="defaultErrorView" value="error"/>
             <property name="exceptionMappings">
                    <props>
                           <prop key="RuntimeException">error</prop>
                    </props>
             </property>
</bean>
<bean name="excelView" class="board.model.ExcelView"/>
세개의 ViewResolver를 설정하였고, 위에서부터 일반 JSP파일의 요청을 받아들이는 InternalResourceViewResolver, 두번째는 뷰 이름과 동일한 빈객체를 뷰 객체로 사용하는 BeanNameViewResolver로 여기서 구현하는 엑셀파일 다운로드요청을 받게 된다, 세번째는 애러페이지를 담당하는 ViewResolver 이다.  마지막에 설정되어있는 excelView는 엑셀파일을 생성하는 클래스이며 excelView라는 이름의 뷰 요청이 들어올때 사용된다.

#다운로드 요청
/excel_transform_controller?target=article
/excel_transform_controller?target=comment
/excel_transform_controller?target=file
각각 컨트롤러로 요청되는 주소이며, target 파라미터의 값에따라, 게시글 목록, 댓글 목록, 파일 목록을 엑셀파일로 생성하게된다.

#Controller.java
//엑셀파일 변환  다운로드
@RequestMapping("/excel_transform_controller")
public String excelTransform(@RequestParam String target, Map<String,Object> ModelMap) throws Exception{
List<Object> excelList= null;
      excelList = service.getAllObjects(target);
            
   ModelMap.put("excelList", excelList);
      ModelMap.put("target", target);
      return "excelView";
}
들어온 요청의 파라미터값 target에 따라 게시글목록, 댓글목록, 파일목록을 불러오게 되며, 불러온 List객체를 excelList 프로퍼티에 저장후 ModelMap 객체에 추가한다.
여기서 ModelMap객체에 추가된 항목들은 Response 응답에 추가되어 뷰에 추가되어 전달된다. 모든 엑셀파일 생성이 이루어지면 excelView 라는 뷰 이름을 리턴하고 스프링 설정파일에서는 BeanNameViewResolver가 excelView 빈 객체를 실행하게 된다.

#ServiceImpl.java
@Override
public List<Object> getAllObjects(String target){
       if(target.equals("article")) return dao.getAllArticles();
       if(target.equals("comment")) return dao.getAllComments();
       if(target.equals("file")) return dao.getAllFiles();
       return null;
}
컨트롤러에서 ModelMap에 추가한 target의 값에 따라 서비스단에서 필요한 목록을 가져와 리턴한다.

#excelView.java
package board.model;

import java.net.URLEncoder;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.web.servlet.view.document.AbstractExcelView;

public class ExcelView extends AbstractExcelView{
       @Override
       protected void buildExcelDocument(Map<String,Object> ModelMap,HSSFWorkbook workbook, HttpServletRequest request, HttpServletResponse response) throws Exception{
             String excelName = ModelMap.get("target").toString();
             HSSFSheet worksheet = null;
             HSSFRow row = null;
             if(excelName.equals("article")){
                    excelName=URLEncoder.encode("게시글","UTF-8");
                    worksheet = workbook.createSheet(excelName+ " WorkSheet");
                    @SuppressWarnings("unchecked")
                    List<BoardArticle> list = (List<BoardArticle>)ModelMap.get("excelList");
                    row = worksheet.createRow(0);
                    row.createCell(0).setCellValue("글번호");
                    row.createCell(1).setCellValue("제목");
                    row.createCell(2).setCellValue("날짜");
                    row. createCell(3).setCellValue("글쓴이");
                    row.createCell(4).setCellValue("비밀번호");
                    row.createCell(5).setCellValue("내용");
                    for(int i=1;i<list.size()+1;i++){
                           row = worksheet.createRow(i);
                           row.createCell(0).setCellValue(list.get(i-1).getArticleNo());
                           row.createCell(1).setCellValue(list.get(i-1).getArticleTitle());
                           row.createCell(2).setCellValue(list.get(i-1).getArticleDate());
                           row.createCell(3).setCellValue(list.get(i-1).getArticleWriter());
                           row.createCell(4).setCellValue(list.get(i-1).getArticlePw());
                           row.createCell(5).setCellValue(list.get(i-1).getArticleContent());
                    }
             }
             if(excelName.equals("comment")){
                    @SuppressWarnings("unchecked")
                    List<BoardComment> list = (List<BoardComment>)ModelMap.get("excelList");
                    excelName=URLEncoder.encode("댓글","UTF-8");
                    worksheet = workbook.createSheet(excelName+ " WorkSheet");
                    row = worksheet.createRow(0);
                    row.createCell(0).setCellValue("댓글번호");
                    row.createCell(1).setCellValue("게시글번호");
                    row.createCell(2).setCellValue("날짜");
                    row.createCell(3).setCellValue("글쓴이");
                    row.createCell(4).setCellValue("비밀번호");
                    row.createCell(5).setCellValue("내용");
                    for(int i=1;i<list.size()+1;i++){
                           row = worksheet.createRow(i);
                           row.createCell(0).setCellValue(list.get(i-1).getCommentNo());
                           row.createCell(1).setCellValue(list.get(i-1).getArticleNo());
                           row.createCell(2).setCellValue(list.get(i-1).getCommentDate());
                           row.createCell(3).setCellValue(list.get(i-1).getCommentWriter());
                           row.createCell(4).setCellValue(list.get(i-1).getCommentPw());
                           row.createCell(5).setCellValue(list.get(i-1).getCommentContent());
                    }
             }
             if(excelName.equals("file")){
                    @SuppressWarnings("unchecked")
                    List<BoardFile> list = (List<BoardFile>)ModelMap.get("excelList");
                    excelName=URLEncoder.encode("파일","UTF-8");
                    worksheet = workbook.createSheet(excelName+ " WorkSheet");
                    row = worksheet.createRow(0);
                    row.createCell(0).setCellValue("파일번호");
                    row.createCell(1).setCellValue("게시글번호");
                    row.createCell(2).setCellValue("파일경로");
                    row.createCell(3).setCellValue("파일이름");
                    row.createCell(4).setCellValue("파일크기");
                    for(int i=1;i<list.size()+1;i++){
                           row = worksheet.createRow(i);
                           row.createCell(0).setCellValue(list.get(i-1).getFileNo());
                           row.createCell(1).setCellValue(list.get(i-1).getArticleNo());
                           row.createCell(2).setCellValue(list.get(i-1).getFilePath());
                           row.createCell(3).setCellValue(list.get(i-1).getFileName());
                           row.createCell(4).setCellValue(list.get(i-1).getFileSize());
                    }
             }
             response.setContentType("Application/Msexcel");
             response.setHeader("Content-Disposition", "ATTachment; Filename="+excelName+"-excel");
       }
}
매우 단순한 엑셀파일을 생성하는 코드이다. 단지 컬럼명과 데이터만 엑셀파일로 생성하였다. 여기서는 다운로드를 구현하였기때문에 response 객체에 몇가지 설정을 추가하였다.

#생성된 엑셀파일(게시글)


Tomcat에서 JSP파일의 한글깨짐 방지(인코딩)

Tomcat에서 JSP파일의 한글깨짐 방지

1. Get방식으로 넘어가는 파라미터 한글인코딩하게 하는법

  위치 : 'C:\java\Tomcat 5.5\conf\serverl.xml' 파일을 아래와 같이 변경.
         URIEncoding="euc-kr" 를 추가 삽입 한후 저장
         톰캣 재시작후 다시 확인 하면 됨.
  <Connector port="8080" maxHttpHeaderSize="8192"
      maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
      enableLookups="false" redirectPort="8443" acceptCount="100"
      connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="euc-kr" />

2. JSP에서 엑셀로 출력시 한글깨짐현상

    response.setHeader("Content-Disposition", "attachment; filename=export.xls");
    response.setHeader("Content-Description", "JSP Generated Data");
    response.setContentType("application/vnd.ms-excel");
    <meta http-equiv="Content-Type" content="application/vnd.ms-excel;charset=euc-kr">
    추가한다.

3. ContentType이"Text/html"이 아닐때 한글 인코딩(예 contentType="image/gif")

     String aa = "한글~!!";
     aa = new String(aa.getBytes("8859_1"),"euc-kr");
     g.setFont(new Font("Gulim", Font.ITALIC, 15));
     g.drawString("HelloWorld~!!", 10, 50);
     g.drawString(aa, 10, 80);

4. jsp 페이지상단에 <%@ page contentType="text/html;charset=euc-kr" %>삽입

5. Post로 넘어온값 위에 아래 문장 선언(단 ,get 방식은 지원안함) 
                             
    request.setCharacterEncoding("euc-kr");

JSTL - JSTL 표현식에서 연산자 사용하기(수식)

원본주소 : http://jxls.sourceforge.net/reference/formulas.html


Overview

This section demonstrates how to apply different formulas to your exported data. First any static Excel formulas (which are supported by POI) will be copied to result Excel file untouched. But if you want to apply formula to dynamic data like exported collections you have to use predefined notation. Any cell with value starting with $[ and ending with ] will be rendered as a formula cell. For example
                            $[formula]
            
where formula is the real formula which will be processed by jXLS engine.

Formula Cell References notation.

When you reference a worksheet cell in a jXLS formula and that cell is transformed into some other cell or a set of cells the cell reference in the formula will be updated accordingly. For example if you have a formula like
                                $[E5 + B4 * 5]
            
And after jXLS transformation cell E5 turns to E20 and cell B4 turns to cell B15 the result formula will look like
                                 E20 + B15 * 5
            
Let's consider more complex sample where a source cell was duplicated and turned into several cells forming a cell range. For example if we have a formula like
                $[SUM(C2)]
            
and cell C2 turns into a set of cells C2, C3, C4, C5, C6. This can happen for example if cell C2 is contained in jx:forEach tag body. In this case jXLS detects that result cells form a range C2:C6 and replaces the original cell reference with this range
                SUM(C2:C6)
            
jXLS also detects column ranges like A5:E5 when result cells are A5, B5, C5, D5, E5.
If result cells do not form any cell range original cell will be replaced with list of all cells separated with commas. If in previous example cell C2 is transformed into cells C2, C3, C4, C10, C11, C20 result formula will look like
                SUM(C2,C3,C4,C10,C11,C20)
            
Also you can reference cells from different worksheets in a formula cell. For example you can have following formula referencing cells from other worksheets
                $[SUM(Sheet2!B10) - 'Sheet 1'!D15]
            
jXLS updates formula cell references throughout the workbook during excel template transformation. It means for example that any transformation that changes cell original location will reflect new cell location in all affected formulas. If we have jx:forEach tag like this
                <jx:forEach items="${employees}" var="employee">
                ${employee.name} | ${employee.payment}
                <jx:forEach>
            
And assuming that before transformation ${employee.payment} was located in a cell B5 and after transformation we have employee payments in all cells from B5 to B10 then if any other cell references original cell B5 like for example $[SUM(B5)] then all such formulas will be updated. In this case we will get a formula like SUM(B5:B10).

Default Formula Values

Sometime you may have a situation when all cells referenced in your formula are removed from the sheet. For example it can happen when formula references a cell inside jx:forEach tag and the collection is empty. To deal with this situation you can use @ symbol to define default formula value. Default formula value will replace the formula only in that case when all underlying cell references were removed during processing.
Example
            $[SUM(B6) + SUM(B13)@0 + (SUM(B20)@0) +SUM(B27)@0 + SUM(B34)]
            
Assuming cells B13 and B27 were removed during transformation you will get Excel output similar to this
                =SUM(B5:B9)+0+(SUM(B18:B21))+0+SUM(B30:B32)
            

JAVA - 자바 문자수 구하기

           public class Pack06 {
              public static void main(String[] args) {
                 if(args.length < 1) {
                    System.err.print("문자열을 입력해주세요!");
                    System.exit(-1);
                 }
                 int numLines = 1;
                 int numWords = 1;
                 int numChars = 0;
                 String s = args[0];
                 for(int i = 0, len = s.length(); i < len; ++i) {
                    switch (s.charAt(i)) {
                       case '/':
                       ++numLines;
.
                       case ' ':
                       ++numWords;
                       break;
                       default:
                       ++numChars;
                       break;
                    }
                 }
                 System.out.println("행수: " + numLines);
                 System.out.println("단어수: " + numWords);
                 System.out.println("문자수: " + numChars);
              }
           }
           //Pack07.java
           public class Pack07 {
              public static void main(String[] args) {
                 if(args.length % 2 != 0) {
                    System.err.println("학생의 수와 점수의 수가 일치하지 않습니다!");
                    System.exit(-1);
                 }
                 int numStudents = args.length / 2;
                 String[] names = new String[numStudents];
                 int[] grades = new int[numStudents];
                 //이름과 점수를 저장 
                 for(int i = 0; i < numStudents; ++i) {
                    names[i] = args[i * 2];
                    grades[i] = Integer.parseInt(args[i * 2 + 1]);
                 }
                 printNameOrder(names, grades);
                 printScoreOrder(names, grades);

              }

              public static void printNameOrder(String[] names, int[] grades) {
                 String[] tempNames = names.clone();
                 int[] tempGrades = grades.clone();
                 for(int i = 0, len = tempNames.length ; i < len; ++i ){
                    for(int j = i + 1; j < len ; ++j ) {
                       if(tempNames[j].compareTo(tempNames[i]) < 0) {
                          String stemp = tempNames[i];
                          tempNames[i] = tempNames[j];
                          tempNames[j] = stemp;
                          int iTemp = tempGrades[i];
                          tempGrades[i] = tempGrades[j];
                          tempGrades[j] = iTemp;
                       }
                    }
                 }
                 System.out.println("-------이름순-------");
                 for(int i = 0, len = names.length; i < len; ++i) {
                    System.out.println(tempNames[i] + "\t" + tempGrades[i]);
                 }
              }
              public static void printScoreOrder(String[] names, int[] grades) {
                 String[] tempNames = names.clone();
                 int[] tempGrades = grades.clone();
                 for(int i = 0, len = tempNames.length ; i < len; ++i ){
                    for(int j = i + 1; j < len ; ++j ) {
                       if(tempGrades[j] > tempGrades[i]) {
                          String stemp = tempNames[i];
                          tempNames[i] = tempNames[j];
                          tempNames[j] = stemp;
                          int iTemp = tempGrades[i];
                          tempGrades[i] = tempGrades[j];
                          tempGrades[j] = iTemp;
                       }
                    }
                 }
                 System.out.println("-------성적-------");
                 for(int i = 0, len = names.length; i < len; ++i) {
                    System.out.println(tempNames[i] + "\t" + tempGrades[i]);
                 }
              }
           }