팡이네

UbiReport에서 다단 설정을 할 경우 그룹 제목 부분 역시 다단으로 표시되어 이상한 보고서가 출력되는데 아래와 같이 마스터 서브 형태로 설정하면 깔끔한 보고서를 만들 수 있다.


1. 마스터 데이터 컴포넌트 추가

1.1 Group 데이터 컴포넌트 추가

1.1 마스터 데이터 컴포넌트 SQL 설정

1.2 그룹 편집 들어가서 그룹 추가 (GROUP_A) 한 뒤 마스터와 서브를 연결할 컬럼을 선택

1.3 GROUP_A Header 밴드를 아래와 같이 설정해준다.

그룹 옵션 > 그룹밴드 반복 체크

그룹 옵션 > 그룹별 페이지 생성 체크



2. GROUP_A Footer 밴드를 아래와 같이 설정한다.

2.1 컴포넌트 옵션 > 포함된 데이터 컴포넌트 크기 확장 체크


3. 페이지 마다 표시될 그룹 헤더 디자인

3.1 확인을 위해 전체 페이지 및 그룹별 페이지 출력 표시

page(), totalpage()

grouppage('A'), grouptotalpage('A')


4. GROUP_A Footer 밴드에 서브 데이터 컴포넌트 추가

4.1 단순한 N-up 형태의 데이터 컴포넌트 추가


5. 서브 데이터 컴포넌트 설정

5.1 단 개수와 진행방향을 설정해준다.


6. 마스터 데이터 컴포넌트와 서브 데이터 컴포넌트를 연결

6.1 서브 데이터 컴포넌트를 클릭하여 컴포넌트 탭의 SQL 결합 버튼 클릭한다.

6.2 마스터와 서브를 연결하는 컬럼을 추가한다.


7. 미리보기

7.1 전체 페이지가 17 페이지이며 그룹 1의 페이지는 4페이지

7.2 그룹1의 멤버들이 표시된다.


SELECT
	WMSYS.WM_CONCAT(A.NAME) AS NAME_LIST
FROM
	T_TEMP A
WHERE
	A.TEMP_ID IN ('TEST1', 'TEST2', 'TEST3')

'Oracle' 카테고리의 다른 글

특정 기간 날짜 모두 SELECT  (0) 2017.05.23
오라클 주차로 주차 날짜 구하기  (0) 2016.03.24

/// 
/// 사진 정보
/// 
public class PhotoInfo
{
	private int maxWidth = 200, maxHeight = 267;
	private int orgWidth = 0, orgHeight = 0;
	private int width = 0, height = 0;
	private bool portraitMode = false;
	private string base64String = null;

	/// 
	/// 사진 정보
	/// 
	public PhotoInfo()
	{

	}

	/// 
	/// 사진 정보
	/// 
	/// 
	public PhotoInfo(MemoryStream ms)
	{
		this.base64String = "data:image/jpg;base64," + Convert.ToBase64String(ms.ToArray());

		System.Drawing.Image img = System.Drawing.Image.FromStream(ms);
		this.orgWidth = img.Width;
		this.orgHeight = img.Height;

		this.portraitMode = (img.Height - img.Width) > 0;

		//세로가 긴 사진인 경우
		if (this.portraitMode)
		{
			if (this.orgHeight > this.maxHeight)
			{
				this.height = this.maxHeight;
				var ratio = (this.maxHeight * 1.0) / (this.orgHeight * 1.0);
				this.width = (int)Math.Round(this.orgWidth * ratio);
				if (this.width > maxWidth)
				{
					this.width = maxWidth;
					ratio = (this.maxWidth * 1.0) / (this.orgWidth * 1.0);
					this.height = (int)Math.Round(this.orgHeight * ratio);
				}
			}
			else
			{
				this.height = this.orgHeight;
				this.width = this.orgWidth;
				if (this.width > maxWidth)
				{
					this.width = maxWidth;
					var ratio = (this.maxWidth * 1.0) / (this.orgWidth * 1.0);
					this.height = (int)Math.Round(this.orgHeight * ratio);
				}
			}
		}
		//가로가 긴 사진인 경우(LandscapeMode)
		else
		{
			if (this.orgWidth > this.maxWidth)
			{
				this.width = this.maxWidth;
				var ratio = (this.maxWidth * 1.0) / (this.orgWidth * 1.0);
				this.height = (int)Math.Round(this.orgHeight * ratio);
				if (this.height > maxHeight)
				{
					this.height = maxHeight;
					ratio = (this.maxHeight * 1.0) / (this.orgHeight * 1.0);
					this.width = (int)Math.Round(this.orgWidth * ratio);
				}
			}
			else
			{
				this.width = this.orgWidth;
				this.height = this.orgHeight;
				if (this.height > maxHeight)
				{
					this.height = maxHeight;
					var ratio = (this.maxHeight * 1.0) / (this.orgHeight * 1.0);
					this.width = (int)Math.Round(this.orgWidth * ratio);
				}
			}
		}
	}

	/// 
	/// 사진 최대 너비
	/// 
	public int MaxWidth { get { return maxWidth; } }
	/// 
	/// 사진 최대 높이
	/// 
	public int MaxHeight { get { return maxHeight; } }
	/// 
	/// 원본 사진 너비
	/// 
	public int OrgWidth { get { return this.orgWidth; } }
	/// 
	/// 원본 사진 높이
	/// 
	public int OrgHeight { get { return this.orgHeight; } }
	/// 
	/// 사진 너비
	/// 
	public int Width { get { return this.width; } }
	/// 
	/// 사진 높이
	/// 
	public int Height { get { return this.height; } }
	/// 
	/// 사진 가로방향여부
	/// 
	public bool PortraitMode { get { return this.portraitMode; } }
	/// 
	/// Base64 문자열
	/// 
	public string Base64String { get { return base64String; } }

	/// 
	/// 사진 정보 표시
	/// 
	/// 
	public void SetImage(Image image)
	{
		if (this.Base64String != null)
		{
			image.ImageUrl = this.Base64String;

			image.Height = this.Height;
			image.Width = this.width;
		}
	}
}

	if (!fileUpload.HasFile)
	{
		Alert("업로드할 사진이 없습니다.");
		Response.End();
	}
	
	var fileLength = fileUpload.PostedFile.ContentLength;
	if (fileLength > 1024000)
	{
		Alert("1MB 이하의 사진만 업로드 할 수 있습니다.");
		Response.End();
	}

	byte[] photoData = new byte[fileLength - 1];
	photoData = fileUpload.FileBytes;
	
	var userID = "";
	var msg = "FAIL";
	var query = "INSERT INTO PHOTO (USER_ID, PHOTO) VALUES ('{0}', :PHOTO)";
	//var query = "UPDATE PHOTO SET PHOTO = :PHOTO WHERE USER_ID = '{0}'";
	query = string.Format(query, userID);
	
	try
	{
		using (var conn = new OracleConnect(connStr))
		{
			var cmd = conn.CreateCommand();
			cmd.CommandType = CommandType.Text;
			cmd.CommandText = query;

			var param = cmd.Parameters.Add(":PHOTO", OracleType.Blob);
			param.Direction = ParameterDirection.Input;
			param.Value = photoData;

			var result = cmd.ExecuteNonQuery();

			if (result == 1)
			{
				msg = "SUCCESS";
			}
		}
	}
	catch (Exception ex)
	{
		throw ex;
	}


테이블 안에 있는 체크박스 모두 선택 및 해제
테이블 ID = 'xxxxx_tblList'
전체 선택 체크박스 ID = 'xxxxx_chkAll' 인 경우 뒷부분 선택자 id$ 로 선택
전체 선택 체크박스 역시 영향받기 때문에 thead, tbody 태그로 구분해서
tbody에 있는 체크박스만 처리

$(document).ready(function () {
	$('input[id$="chkAll"]').click(function () {
		var tbl = $('table[id$="tblList"]');
		var checked = $(this).is(':checked');
		$('tbody tr td input:checkbox', tbl).each(function () {
			$(this).prop('checked', checked);
		})
	});
});

//날짜인지 검사
function isDate(d, c) {
    var y, m, d;
    if (d.length == 8) {
        y = parseInt(d.substr(0, 4));
        m = parseInt(d.substr(4, 2));
        d = parseInt(d.substr(6, 2));
    }
    else if (d.length == 10) {
        if (c == null) c = '-';
        var a = d.split(c);
        if (a.length != 3) return false;

        y = parseInt(a[0]);
        m = parseInt(a[1]);
        d = parseInt(a[2]);
    }
    else {
        return false;
    }

    var date = new Date(y, m - 1, d);

    return (date.getFullYear() == y && date.getMonth() + 1 == m && date.getDate() == d);
}

'Javascript & JQuery' 카테고리의 다른 글

사용자 웹 브라우저 및 버전 확인  (0) 2017.03.21
체크박스 전체 선택 및 해제  (0) 2016.04.01
숫자 키입력 검사  (0) 2016.04.01

//숫자 키입력 검사
function isNumberKeyDown(e) {
    e = e || window.event;
    var keyCode = (e.keyCode ? e.keyCode : e.which);

    if (keyCode == 8 || keyCode == 9 || keyCode == 27 || keyCode == 46) return true;	//BackSpace, Tab, ESC, Delete
    if (keyCode == 35 || keyCode == 36 || keyCode == 37 || keyCode == 39) return true;	//Home, End, Left, Right Arrow
    if (e.ctrlKey || e.shiftKey || keyCode == 13) return false; //Enter

    return ((keyCode > 47 && keyCode < 58) || (keyCode > 95 && keyCode < 106));
}



위와 같이 처리해도 한글은 입력되기 때문에 한글 입력을 방지하기 위해 ime-mode 스타일 추가

SELECT
	TO_CHAR(EXAM_DATE, 'IW') AS WEEK_NO
	,TO_CHAR(EXAM_DATE, 'YYYYMMDD') AS EXAMDATE
	,DECODE(TO_CHAR(EXAM_DATE, 'D'), '1', '일', '2', '월', '3', '화', '4', '수', '5', '목', '6', '금', '토') AS WEEK_NAME
FROM
	(
		SELECT
			TO_DATE('20160321', 'YYYYMMDD') + (ROWNUM - 1) AS EXAM_DATE
		FROM
			DICTIONARY
		WHERE
			ROWNUM < 8
	) A

'Oracle' 카테고리의 다른 글

특정 기간 날짜 모두 SELECT  (0) 2017.05.23
여러 행의 문자열을 한 행으로 표시  (0) 2016.04.20

알프레스코 웹스크립트를 이용한 사이트 생성

/**
 * 사이트를 생성한다.
 * @param siteName		사이트명(빈칸, 특수문자 불가)
 * @param title			사이트 제목
 * @param description	사이트 설명
 * @param visibility	공개유형(PUBLIC/PRIVATE/MODERATED)
 * @return
 */
public boolean createSite(String siteName, String title, String description, String visibility)
{
	String doLoginUrl = ALFRESCO_SERVER_URL +"/share/page/dologin";
	String dashboardUrl = ALFRESCO_SERVER_URL +"/share/page/user/admin/dashboard";
	String createSiteUrl = ALFRESCO_SERVER_URL +"/share/service/modules/create-site";
	
	CloseableHttpClient client = getHttpClient();
	
	try
	{
		List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
		params.add(new BasicNameValuePair("username", ALFRESCO_ADMIN_ID));
		params.add(new BasicNameValuePair("password", ALFRESCO_ADMIN_PASS));
	
		HttpPost loginPost = new HttpPost(doLoginUrl);
		loginPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
		loginPost.setEntity(new UrlEncodedFormEntity(params));
		
		CloseableHttpResponse response = client.execute(loginPost);

		try
		{
			StatusLine statusLine = response.getStatusLine();
			
			//알프레스코는 로그인 후 Share 페이지로 이동하기 때문에
			//getStatusCode() 리턴값이 SC_OK가 아니라 SC_MOVED_TEMPORARILY
			if (statusLine.getStatusCode() == HttpStatus.SC_MOVED_TEMPORARILY)
			{
				org.apache.http.Header[] headers = loginPost.getAllHeaders();

				String JSESSIONID = "";
				String alfUsername3 = "";
				String alfLogin = "";
				
				//---------------------------------------
				//로그인 쿠키값 추출
				//---------------------------------------
				for (int i = 0; i < headers.length; i++)
				{
					Integer idxJsession = headers[i].toString().indexOf("JSESSIONID=");
					if (idxJsession > -1)
					{
						JSESSIONID = headers[i].toString().substring(idxJsession +11, idxJsession +11 +32);
					}
					
					Integer idxAlfUsername3 = headers[i].toString().indexOf("alfUsername3=");
					if (idxAlfUsername3 > -1)
					{
						alfUsername3 = headers[i].toString().substring(idxAlfUsername3 +13, idxAlfUsername3 +13 +5);
					}
					
					Integer idxAlfLogin = headers[i].toString().indexOf("alfLogin=");
					if (idxAlfLogin > -1)
					{
						alfLogin = headers[i].toString().substring(idxAlfLogin +9, idxAlfLogin +9 +10);
					}
				}
				
				//---------------------------------------
				//데시보드
				//---------------------------------------
				String cookie = "JSESSIONID="+ JSESSIONID +";"
						+ "alfLogin="+ alfLogin +";"
						+ "alfUsername3="+ alfUsername3 +";";
				
				HttpGet dashboadrGet = new HttpGet(dashboardUrl);
				dashboadrGet.setHeader("Content-Type", "application/json");
				dashboadrGet.setHeader("Accept", "application/json");
				dashboadrGet.setHeader("Cookie", cookie);
				
				CloseableHttpResponse response2 = client.execute(dashboadrGet);
				
				try
				{
					StatusLine statusLine2 = response2.getStatusLine();
					if (statusLine2.getStatusCode() == HttpStatus.SC_OK)
					{
						org.apache.http.Header[] headers2 = dashboadrGet.getAllHeaders();
						
						String csrfToken = "";
					
						for (int i = 0; i < headers2.length; i++)
						{
							Integer idxCsrfToken = headers2[i].toString().indexOf("Alfresco-CSRFToken=");
							if (idxCsrfToken > -1)
							{
								csrfToken = headers2[i].toString().substring(idxCsrfToken +19, idxCsrfToken +19 +50);
							}
						}
						
						//---------------------------------------
						//사이트 생성
						//---------------------------------------
						String cookie2 = cookie +" Alfresco-CSRFToken="+ csrfToken +";";
						
						JSONObject site = new JSONObject();
						site.put("shortName", siteName);
						site.put("sitePreset", "site-dashboard");
						site.put("title", title);
						site.put("description", description);
						site.put("visibility", visibility);

						HttpPost createSitePost = new HttpPost(createSiteUrl);
						createSitePost.setHeader("Content-Type", "application/json");
						createSitePost.setHeader("Accept", "application/json");
						createSitePost.setHeader("Cookie", cookie2);
						createSitePost.setEntity(new StringEntity(site.toString(), ContentType.create("text/plain", Consts.UTF_8)));
						
						CloseableHttpResponse response3 = client.execute(createSitePost);
						
						try
						{
							StatusLine statusLine3 = response3.getStatusLine();
							if (statusLine3.getStatusCode() == HttpStatus.SC_OK)
							{
								logger.info(String.format("★★★ %s Site Created!!!★★★", siteName));
								return true;
							}
							else
							{
								logger.error("Method failed createSitePost: "+ response3.getStatusLine());
							}
						}
						catch (Exception e)
						{
							logger.error(e.getMessage());
						}
						finally
						{
							response3.close();
						}
					}
					else
					{
						logger.error("Method failed dashboadrGet: "+ response2.getStatusLine());
					}
				}
				catch (Exception e)
				{
					logger.error(e.getMessage());
				}
				finally
				{
					response2.close();
				}
			}
			else
			{
				logger.error("Method failed loginPost: "+ response.getStatusLine());
			}
		}
		catch (Exception e)
		{
			logger.error(e.getMessage());
		}
		finally
		{
			response.close();
		}
	}
	catch (Exception e)
	{
		logger.error(e.getMessage());
	}
	
	return false;
}

사이트 정보 조회

public HashMap getSite(CloseableHttpClient client, String siteName)
{
	HttpGet method = null;
	
	try
	{
		//	/alfresco/s/api/sites/{shortname}
		String url = String.format("%s/api/sites/%s", ALFRESCO_SERVER_SVC, siteName);
		method = new HttpGet(url);
		
		CloseableHttpResponse response = client.execute(method);
		
		try
		{
			StatusLine statusLine = response.getStatusLine();
			
			if (statusLine.getStatusCode() == HttpStatus.SC_OK)
			{
				return createResponse(response);
			}
			else
			{
				logger.error(statusLine.getStatusCode() +" "+ statusLine.getReasonPhrase());
			}
		}
		finally
		{
			response.close();
		}
	}
	catch (Exception e)
	{
		e.printStackTrace();
	}
	finally
	{
		method.releaseConnection();
	}
	
	return null;
}

사이트 존재여부

/**
 * 사이트 존재여부
 * @param client
 * @param siteName	사이트명
 * @return
 */
public boolean existSite(CloseableHttpClient client, String siteName)
{
	return (this.getSite(client, siteName) != null);
}

JSON 데이터 변환

/**
 * 서버 반환 데이터를 HashMap으로 변환한다.
 * @param response
 * @return
 */
private HashMap createResponse(CloseableHttpResponse response)
{
	try
	{
		HttpEntity entity = response.getEntity();
		
		if (entity != null)
		{
			InputStream instream = entity.getContent();
			
			try
			{
				return createResponse(instream);
			}
			finally
			{
				instream.close();
			}
		}
	}
	catch (Exception e)
	{
		e.printStackTrace();
	}
	
	return null;
}

Alfresco Share Login 페이지에서 CSRF 필터 오류 해결법 2가지


알프레스코 5.0 버전으로 오면서 보안이 강화되어 기존 방법으로 CSRF 토큰값을 설정해도
오류가 발생한다. 아래 페이지에서 그 오류에 대한 해결법을 2가지 제시한다.


2번째 해법 - CSRF Token Filter 비활성


알프레스코의 아래 설정 파일에서 “CSRFPolicy” 설정 부분의 주석을 해제한다.

TOMCAT_HOME/shared/classes/alfresco/web-extension/share-config-custom.xml


<!-- Disable the CSRF Token Filter -->
<!--
<config evaluator="string-compare" condition="CSRFPolicy" replace="true">
<filter/>
</config>
-->