팡이네

마이플랫폼에서 Base64 이미지 문자열을 이미지 컴포넌트에 표시하고자 할 때

java 단에서 먼저 해당 컬럼을  DB에서 조회한 다음 일반적인 DRRecordSet으로 반환하면

String 데이터 컬럼으로 변환되어 이미지 컴포넌트에 표시하지 못한다.


그래서 DRRecordSet을 새로 생성하여 해당 컬럼을 BLOB로 만들어서 반환하면

이미지 컴포넌트에서 이미지를 제대로 표시할 수 있다.


DSRecordSet rs = DB에서 조회한 목록


DSRecordSet rs2 = new DSRecordSet();

rs2.addColumn("base64Image", ColumnInfo.CY_COLINFO_BLOB, -1);


for (int i = 0; i < rs.getRowCount(); i++) {

int row = rs2.appendRow();

String imageData = rs.getColumn(row, "base64Image").toString();

rs2.setColumn(row, "base64Image", Base64.decode(imageData.getBytes()));

}


생성한 rs2를 반환한다.


이후 마이플랫폼에서 원하는 이미지 컴포넌트에 표시한다.


imgPhoto.ImageID = ds.GetColumn(nRow, 'base64Image');


단, 여기서 주의할 점은 이미지 컴포넌트 imgPhoto의 ImageID 값은 항상 null 이다.

그래서 if (imgPhoto.ImageID != '')와 같은 구문은 항상 거짓이 된다.


그리고 이미지 컴포넌트의 이미지를 지우거나 초기화할 경우 빈문자열 대신 null을 이용한다. imgPhoto.ImageID = null

이미지 크기 조절

/**
 * 사진 이미지 크기 조절
 * @param img
 * @param width
 * @param height
 * @return
 */
private BufferedImage resizeImage(BufferedImage img, int width, int height) {
	//int type = img.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : img.getType();			//png = TYPE_INT_ARGB
	
	Image tmp = img.getScaledInstance(width, height, Image.SCALE_SMOOTH);
	BufferedImage resized = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);	//jpeg = TYPE_INT_RGB
	Graphics2D g2d = resized.createGraphics();
	g2d.drawImage(tmp, 0, 0, null);
	g2d.dispose();
	return resized;
}

사진 이미지 Base 64 문자열 변환

private String resizePhoto(String filePath, int MAX_SIZE) {
	try {
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		
		//업로드 된 이미지(원본) 파일 읽기
		File file = new File(filePath);
		BufferedImage orgImage = ImageIO.read(file);
		BufferedImage resizedImage = null;
		
		int imageWidth = orgImage.getWidth();
		int imageHeight = orgImage.getHeight();
		
		//가로가 긴 이미지
		if (imageWidth > imageHeight) {
			if (imageWidth > MAX_SIZE) {
				double height = (double)imageHeight / (double)imageWidth * (double)MAX_SIZE;
				//가로 크기 = MAX_SIZE, 세로 크기 = height
				resizedImage = resizeImage(orgImage, MAX_SIZE, (int)height);
			}
		//세로가 긴 이미지
		} else {
			if (imageHeight > MAX_SIZE) {
				double width = (double)imageWidth / (double)imageHeight * (double)MAX_SIZE;
				//가로크기 = width, 세로 크기 = MAX_SIZE
				resizedImage = resizeImage(orgImage, (int)width, MAX_SIZE);
			}
		}
		
		//이미지 크기 변경 = resizedImage 아니면 원본 이미지 = orgImage
		ImageIO.write((resizedImage != null) ? resizedImage : orgImage, "jpeg", os);
		
		return Base64.getEncoder().encodeToString(os.toByteArray());	//base64 문자열 변환
	} catch (FileNotFoundException ex) {
		System.out.println("▶▶▶ File not found in [resizePhoto] " + ex);
	} catch (IOException ex) {
		System.out.println("▶▶▶ Error in [resizePhoto] " + ex);
	}
	
	return null;
}

'Java' 카테고리의 다른 글

날짜 관련 유틸리티  (0) 2018.10.23
JDK 8 인스톨 없이 설치하기  (0) 2018.10.20
POI, Excel 셀 생성  (0) 2015.06.30
POI, Excel 숫자 셀 생성  (0) 2015.06.30
POI, Excel 병합 셀 생성  (0) 2015.06.30

Angular에서 localhost Web API를 호출할 때 아래와 같은 오류가 발생할 경우


http failure response for (unknown url) 0 unknown error


You’ve run afoul of the Same Origin Policy – it says that every AJAX request must match the exact hostprotocol, and port of your site. Things that might cause this:

서버측에 CORS(Cross-Orgion Resource Sharing) Header를 추가해준다.

그 외 방법은 아래 링크를 참조한다.

https://daveceddia.com/access-control-allow-origin-cors-errors-in-angular/

https://stackoverflow.com/questions/29024313/asp-net-webapi2-enable-cors-not-working-with-aspnet-webapi-cors-5-2-3


I just added custom headers to the Web.config and it worked like a charm.

On configuration - system.webServer:

<httpProtocol>   <customHeaders>     <add name="Access-Control-Allow-Origin" value="*" />     <add name="Access-Control-Allow-Headers" value="Content-Type" />   </customHeaders> </httpProtocol>


MVC4 Quick Tip #3–Removing the XML Formatter from ASP.Net Web API

In Global.asax add the line:

GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();

like so:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);

    BundleTable.Bundles.RegisterTemplateBundles();
    GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
}


'C#' 카테고리의 다른 글

폴더 압축 (SharpZipLib 사용)  (0) 2017.11.28
ClosedXML 사용  (0) 2017.05.17
ASP.NET 엑셀 출력 스타일  (0) 2016.08.31
사진 이미지 관련 클래스  (0) 2016.04.14
오라클 BLOB 등록 및 조회  (0) 2016.04.14

* 특정 폴더에 있는 파일 압축
* ICSharpCode.SharpZipLib.dll 사용
* folderPath : 폴더 경로(서버 물리 경로)

	public void DownloadZipFile(string folderPath)
	{
		if (Directory.Exists(folderPath))
		{
			var zipFilePath = string.Format("{0}.zip", folderPath);

			//-----------------------------------
			//파일 압축
			//-----------------------------------
			try
			{
				var files = Directory.GetFiles(folderPath);

				// 'using' statements guarantee the stream is closed properly which is a big source
				// of problems otherwise.  Its exception safe as well which is great.
				using (ZipOutputStream s = new ZipOutputStream(File.Create(zipFilePath)))
				{
					s.SetLevel(9); // 0 - store only to 9 - means best compression

					byte[] buffer = new byte[4096];

					foreach (string file in files)
					{
						// Using GetFileName makes the result compatible with XP
						// as the resulting path is not absolute.
						var entry = new ZipEntry(Path.GetFileName(file));

						// Setup the entry data as required.

						// Crc and size are handled by the library for seakable streams
						// so no need to do them here.

						// Could also use the last write time or similar for the file.
						entry.DateTime = DateTime.Now;
						s.PutNextEntry(entry);

						using (FileStream fs = File.OpenRead(file))
						{
							// Using a fixed size buffer here makes no noticeable difference for output
							// but keeps a lid on memory usage.
							int sourceBytes;
							do
							{
								sourceBytes = fs.Read(buffer, 0, buffer.Length);
								s.Write(buffer, 0, sourceBytes);
							} while (sourceBytes > 0);
						}
					}

					// Finish/Close arent needed strictly as the using statement does this automatically

					// Finish is important to ensure trailing information for a Zip file is appended.  Without this
					// the created file would be invalid.
					s.Finish();

					// Close is important to wrap things up and unlock the file.
					s.Close();
				}
			}
			catch
			{
				throw new Exception("파일을 압축하는 도중 오류가 발생하였습니다.");
			}

			//-----------------------------------
			//폴더 삭제
			//-----------------------------------
			try
			{
				Directory.Delete(folderPath, true);
			}
			catch
			{
				throw new Exception("압축폴더를 다운로드 하는 도중 오류가 발생하였습니다.");
			}

			//-----------------------------------
			//압축파일 다운로드
			//-----------------------------------
			try
			{
				this.DownloadZipFile(zipFilePath, true);
			}
			catch
			{
				throw new Exception("압축파일을 다운로드 하는 도중 오류가 발생하였습니다.");
			}
		}
	}

* DownloadZipFile() 서버의 압축파일(ZIP)을 다운로드한다.

	/// 
	/// 서버의 압축파일(ZIP)을 다운로드한다.
	/// 
	/// 서버 파일 경로
	/// 다운로드 후 파일 삭제여부
	public void DownloadZipFile(string filePath, bool deleteAfterDown)
	{
		var fileName = System.IO.Path.GetFileName(filePath);

		//한글 깨어짐 방지
		var saveFileName = HttpUtility.UrlEncode(fileName).Replace("+", "%20");

		var response = System.Web.HttpContext.Current.Response;
		
		//아래 방식을 사용하면 다운로드 후 압축파일이 깨어졌다는 메시지 표시
		/*
		response.ClearContent();
		response.Clear();
		response.ContentType = "application/zip";
		response.Charset = "utf-8";
		response.AddHeader("Content-Disposition", "attachment; filename=" + saveFileName + ";");
		response.TransmitFile(filePath);
		response.Flush();

		if (deleteAfterDown)
		{
			//파일 삭제
			var deleteFile = new System.IO.FileInfo(filePath);
			if (deleteFile.Exists)
			{
				System.IO.File.Delete(filePath);
			}
		}

		response.End();
		*/

		//---------------------------------------------
		//제네릭 처리기 사용
		//---------------------------------------------
		//Response.TransmitFile() 메소드 사용시 압축파일이 깨졌다는 메시지 표시
		response.Redirect(string.Format("~/DownloadZipFile.ashx?fileName={0}", saveFileName));
	}

* DownloadZipFile.ashx 파일 내용

<%@ WebHandler Language="C#" Class="DownloadZipFile" %>

using System;
using System.IO;
using System.Web;

public class DownloadZipFile : IHttpHandler
{
	public void ProcessRequest(HttpContext context)
	{
		var request = context.Request;
		var response = context.Response;
		var fileName = request.QueryString["fileName"];

		if (!string.IsNullOrEmpty(fileName))
		{
			var saveFileName = HttpUtility.UrlEncode(fileName).Replace("+", "%20");
			var fullPath = string.Format("{0}{1}", context.Server.MapPath(@"~/Download/"), fileName);	//다운로드 파일 경로
			
			response.ClearContent();
			response.Clear();
			response.ContentType = "application/zip";
			response.Charset = "utf-8";
			response.AddHeader("Content-Disposition", string.Format(@"attachment; filename=""{0}"";", saveFileName));
			response.TransmitFile(fullPath);
			response.Flush();

			//엑셀 파일 삭제
			var deleteFile = new FileInfo(fullPath);
			if (deleteFile.Exists)
			{
				File.Delete(fullPath);
			}
			
			response.End();
		}
		else
		{
			var script = "<script type='text/javascript'>alert('압축 파일을 찾을 수 없습니다.');history.back();</script>";
			response.Write(script);
			response.End();
		}
	}

	public bool IsReusable
	{
		get
		{
			return false;
		}
	}
}

CONNECT BY LEVEL을 사용한다.
SELECT
	TO_CHAR(TO_DATE('20170301', 'YYYYMMDD') + LEVEL - 1, 'YYYY-MM-DD') AS CAL_DATE 
FROM
	DUAL
CONNECT BY
	LEVEL <= 31

'Oracle' 카테고리의 다른 글

여러 행의 문자열을 한 행으로 표시  (0) 2016.04.20
오라클 주차로 주차 날짜 구하기  (0) 2016.03.24

ClosedXML 사용

C#2017. 5. 17. 15:42

* AddWorksheet() 새로운 워크시트를 만든다.

public IXLWorksheet AddWorksheet(XLWorkbook wb, string sheetName)
{
	var ws = wb.AddWorksheet(sheetName);
	ws.Style.Font.SetFontName("맑은 고딕");	//기본글꼴
	ws.Style.Font.SetFontSize(10);			//기본글꼴크기
	ws.Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;	//세로맞춤: 가운데

	return ws;
}

* GetExcelColumn() 지정한 컬럼의 엑셀 컬럼문자를 가져온다.

public string GetExcelColumn(int columnIndex)
	{
		var colString = "";

		if (columnIndex > 26)
		{
			var surplus = columnIndex % 26; if (surplus == 0) surplus = 26;
			var quota = (columnIndex - surplus) / 26;

			//3글자 컬럼명
			if (quota > 26)
			{
				var surplus2 = quota % 26;
				var quota2 = (quota - surplus2) / 26;

				colString = string.Format("{0}{1}{2}", Convert.ToChar(64 + quota2), Convert.ToChar(64 + surplus2), Convert.ToChar(64 + surplus));
			}
			//2글자 컬럼명
			else
			{
				colString = string.Format("{0}{1}", Convert.ToChar(64 + quota), Convert.ToChar(64 + surplus));
			}
		}
		else
		{
			colString = string.Format("{0}", Convert.ToChar(64 + columnIndex));
		}

		return colString;
	}

* AddExcelCell() 지정한 셀에 숫자값을 표시한다.

public IXLCell AddExcelCell(IXLWorksheet ws, int row, int col, int value, string bgColor
						, bool bold, XLAlignmentHorizontalValues hAlign)
{
	var cell = ws.Cell(row, col);
	cell.SetValue(value);
	cell.DataType = XLCellValues.Number;
	cell.Style.NumberFormat.Format = "#,##0;(#,##0);-";
	cell.Style.Alignment.Horizontal = hAlign;
	cell.Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;
	cell.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
	if (bold) cell.Style.Font.Bold = true;
	if (!string.IsNullOrEmpty(bgColor)) cell.Style.Fill.BackgroundColor = XLColor.FromHtml(bgColor);

	return cell;
}

* AddExcelCell() 지정한 셀에 문자열을 표시한다.

public IXLCell AddExcelCell(IXLWorksheet ws, int row, int col, string value, string bgColor, bool bold
						, XLAlignmentHorizontalValues hAlign, XLBorderStyleValues outsideBorder)
{
	var cell = ws.Cell(row, col).SetValue(value);
	cell.DataType = XLCellValues.Text;
	cell.Style.Alignment.Horizontal = hAlign;
	cell.Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;
	cell.Style.Border.OutsideBorder = outsideBorder;
	if (bold) cell.Style.Font.Bold = true;
	if (!string.IsNullOrEmpty(bgColor)) cell.Style.Fill.BackgroundColor = XLColor.FromHtml(bgColor);

	return cell;
}

* AddExcelCell() 지정한 셀에 문자열을 표시하고 병합한다.

public IXLRange AddExcelCell(IXLWorksheet ws, int row, int col, int rowSpan, int colSpan, string value, string bgColor, int width)
{
	var endRow = (rowSpan > 1) ? row + rowSpan - 1 : row;
	var endCol = (colSpan > 1) ? col + colSpan - 1 : col;

	var rg = ws.Range(row, col, endRow, endCol);
	rg.Merge();
	rg.Cell(1, 1).SetValue(value);
	rg.DataType = XLCellValues.Text;
	rg.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
	rg.Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;
	rg.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
	if (!string.IsNullOrEmpty(bgColor)) rg.Style.Fill.BackgroundColor = XLColor.FromHtml(bgColor);
	if (width > 0) rg.FirstCell().WorksheetColumn().Width = width;

	return rg;
}

public IXLRange AddExcelCell(IXLWorksheet ws, int row, IXLRange range, int rowSpan, int colSpan, string value, string bgColor, int width)
{
	var col = range.Cell(1, 1).WorksheetColumn().ColumnNumber() + range.ColumnCount();
	var endRow = (rowSpan > 1) ? row + rowSpan - 1 : row;
	var endCol = (colSpan > 1) ? col + colSpan - 1 : col;

	var rg = ws.Range(row, col, endRow, endCol);
	rg.Merge();
	rg.Cell(1, 1).SetValue(value);
	rg.DataType = XLCellValues.Text;
	rg.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
	rg.Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;
	rg.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
	if (!string.IsNullOrEmpty(bgColor)) rg.Style.Fill.BackgroundColor = XLColor.FromHtml(bgColor);
	if (width > 0) rg.FirstCell().WorksheetColumn().Width = width;

	return rg;
}

* AddExcelFormularCell() 지정한 셀에 엑셀 수식을 표시한다.

public IXLCell AddExcelFormularCell(IXLWorksheet ws, int row, int col, string formular, string bgColor, bool bold, string numberFormat)
{
	var cell = ws.Cell(row, col);
	if (!string.IsNullOrEmpty(formular))
	{
		cell.DataType = XLCellValues.Number;
		if (!string.IsNullOrEmpty(numberFormat)) cell.Style.NumberFormat.Format = numberFormat;
		cell.SetFormulaA1(formular);
	}

	cell.Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;
	cell.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
	if (bold) cell.Style.Font.Bold = true;
	if (!string.IsNullOrEmpty(bgColor)) cell.Style.Fill.BackgroundColor = XLColor.FromHtml(bgColor);

	return cell;
}

* DownloadExcel() 서버의 엑셀 파일을 다운로드한다.

	/// 
	/// 서버의 엑셀 파일을 다운로드한다.
	///		다운로드 후에는 서버의 엑셀 파일을 삭제한다.
	/// 
	/// 실제 서버 물리 경로
	/// 엑셀 파일명
	public void DownloadExcel(string filePath, string fileName)
	{
		//한글 깨어짐 방지
		var saveFileName = HttpUtility.UrlEncode(fileName).Replace("+", "%20");
		//var fullPath = filePath + fileName;

		var response = System.Web.HttpContext.Current.Response;

		//---------------------------------------------------------------------
		//엑셀 파일 다운로드
		//---------------------------------------------------------------------
		//서버의 엑셀 파일 다운로드 후 몇 바이트 늘어남 -> 엑셀 열기 선택 시 복구 메시지 표시
		//---------------------------------------------------------------------
		//response.ClearContent();
		//response.Clear();
		//response.Charset = "utf-8";
		//response.ContentEncoding = System.Text.Encoding.GetEncoding("utf-8");
		////response.ContentType = "application/vnd.msexcel";
		//response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
		//response.AddHeader("Content-Disposition", string.Format(@"attachment; filename=""{0}"";", saveFileName));
		////response.TransmitFile(Server.MapPath("/" + fileName));
		//response.TransmitFile(fullPath);
		//response.Flush();

		//엑셀 파일 삭제
		//var deleteFile = new System.IO.FileInfo(fullPath);
		//if (deleteFile.Exists)
		//{
		//	System.IO.File.Delete(fullPath);
		//}

		//response.End();

		//---------------------------------------------
		//제네릭 처리기 사용
		//---------------------------------------------
		//열기 선택 시 엑셀 파일이 읽기 전용으로 열림
		//---------------------------------------------
		response.Redirect(string.Format("~/DownloadExcelFile.ashx?fileName={0}", saveFileName));
	}

* DownloadExcelFile.ashx 파일 내용

<%@ WebHandler Language="C#" Class="DownloadExcelFile" %>

using System;
using System.IO;
using System.Web;

public class DownloadExcelFile : IHttpHandler
{
	public void ProcessRequest(HttpContext context)
	{
		var request = context.Request;
		var response = context.Response;
		var fileName = request.QueryString["fileName"];

		if (!string.IsNullOrEmpty(fileName))
		{
			var saveFileName = HttpUtility.UrlEncode(fileName).Replace("+", "%20");
			var fullPath = string.Format("{0}{1}", context.Server.MapPath(@"~/Download/"), fileName);	//다운로드 경로
			
			response.ClearContent();
			response.Clear();
			response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
			response.AddHeader("Content-Disposition", string.Format(@"attachment; filename=""{0}"";", saveFileName));
			response.TransmitFile(fullPath);
			response.Flush();

			//엑셀 파일 삭제
			var deleteFile = new FileInfo(fullPath);
			if (deleteFile.Exists)
			{
				File.Delete(fullPath);
			}
			
			response.End();
		}
		else
		{
			var script = "<script type='text/javascript'>alert('엑셀 파일을 찾을 수 없습니다.');history.back();</script>";
			response.Write(script);
			response.End();
		}
	}

	public bool IsReusable
	{
		get
		{
			return false;
		}
	}
}

※ 사용방법

using(var wb = new new XLWorkbook())
{
	var ws = AddWorksheet(wb, "Test Sheet");

	var row = 1;
	var col = 1;
	for (var i = 0; i < list.Length; i++)
	{
		col = 1;

		AddExcelCell(ws, row, col++, list[i]["COL1"].ToString());
		AddExcelCell(ws, row, col++, list[i]["COL2"].ToString());

		row++;
	}
	
	ws.Columns().AdjustToContents();		//열 너비 자동설정(데이터양이 많을 경우 속도가 매우 느려짐)
	wb.SaveAs(@"d:\\example.xlsx");		//서버의 지정한 경로에 저장

	DownloadExcel(@"d:\\example.xlsx");	//서버의 경로에 저장되므로 사용자는 다운로드 필요
}
※ 주의사항
ws.Columns().AdjustToContents();
열 너비 자동설정하는 명령어인데 데이터양이 조금이라도 많을 경우 속도가 매우 느려지므로 조심해서 사용하자.

사용자 웹 브라우저 및 버전 확인

function getBrowserInfo(opt) {
	var ua = navigator.userAgent.toLowerCase();
	
	if (ua.indexOf('android') > -1) return 'Android';
	else if (ua.match(/iphone|ipad|ipot/)) return 'iOS';
	
	if (navigator.appName == 'Microsoft Internet Explorer') {
		if (opt == 'n') return 'Explorer';
		else {
			var re = new RegExp('msie ([0-9]{1,}[\\.0-9]{0,})');
			if (re.exec(ua) !== null) {
				if (opt == 'v')
					return parseInt(RegExp.$1);
				else
					return 'Explorer '+ parseInt(RegExp.$1);
			}
		}
	}
	else if (ua.indexOf('trident') != -1 && navigator.product == 'Gecko') { //IE 11 above
		if (opt == 'n') return 'Explorer';
		else {
			var re = new RegExp('trident/.*rv:([0-9]{1,}[\.0-9]{0,})');
			if (re.exec(ua) != null) {
				if (opt == 'v')
					return parseInt(RegExp.$1);
				else
					return 'Explorer '+ parseInt(RegExp.$1);
			}
		}
	}
	else if (/edge/.test(ua)) {
		if (opt == 'n') return 'Edge';
		else {
			if (opt == 'v')
				return parseInt(/edge\/([\d\.]+)/.exec(ua)[1]);
			else
				return 'Edge '+ parseInt(/edge\/([\d\.]+)/.exec(ua)[1]);
		}
	}
	else if (/chrome/.test(ua)) {
		if (opt == 'n') return 'Chrome';
		else {
			if (opt == 'v')
				return parseInt(/chrome\/([\d\.]+) safari/.exec(ua)[1]);
			else
				return 'Chrome '+ parseInt(/chrome\/([\d\.]+) safari/.exec(ua)[1]);
		}
	}
	else if (/firefox/.test(ua)) {
		if (opt == 'n') return 'FireFox';
		else {
			if (opt == 'v')
				return parseInt(/firefox\/([\d\.]+)/.exec(ua)[1]);
			else
				return 'FireFox '+ parseInt(/firefox\/([\d\.]+)/.exec(ua)[1]);
		}
	}
	else if (/safari/.test(ua)) {
		if (opt == 'n') return 'Safari';
		else {
			if (opt == 'v')
				return parseInt(/version\/([\d\.]+) safari/.exec(ua)[1]);
			else
				return 'Safari '+ parseInt(/version\/([\d\.]+) safari/.exec(ua)[1]);
		}
	}
	
	return 'Other';
}

getBrowserInfo('n');	//웹 브라우저 이름
getBrowserInfo('v');	//웹 브라우저 버전
getBrowserInfo();		//웹 브라우저 이름 + 버전

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

체크박스 전체 선택 및 해제  (0) 2016.04.01
입력 데이터가 제대로 된 날짜인지 검사  (0) 2016.04.01
숫자 키입력 검사  (0) 2016.04.01

1. 기본 '텍스트 줄 바꿈' 속성 제외

기본 엑셀 출력 시 모든 셀에 '텍스트 줄 바꿈' 속성이 설정된다.

이를 방지하려면 아래와 같이 스타일을 설정한다.


<style type="text/css">

td { white-space:nowrap; }

</style>



2. 같은 셀에 2줄 표시

만약 특정 셀에서 같은 셀에 2줄 이상을 표시하고 싶을 때가 있다.

이럴 경우에는 아래와 같이 스타일을 설정한다.


<style type="text/css">

br { mso-data-placement:same-cell; }

</style>


Reponse.Write("<td>이번 셀에서는<br/>이 줄은 다음 줄에 표시</td>");


결과


이번 셀에서는

이 줄은 다음 줄에 표시



3. 기본 '텍스트 줄 바꿈' 속성 제외와 같은 셀 2줄 표시를 동시에 하고 싶은 경우

아래와 같이 스타일을 설정한다.


<style type="text/css">

td { white-space:nowrap; }

br { mso-data-placement:same-cell; }

.same { white-space:normal; }

</style>


Reponse.Write("<td>이번 셀에서는<br/>한 줄에 표시</td>");

Reponse.Write(@"<td class=""same"">이번 셀에서는<br/>이 줄은 다음 줄에 표시</td>");


결과


이번 셀에서는한 줄에 표시


이번 셀에서는

이 줄은 다음 줄에 표시



같은 셀에 2줄 이상 표시하려면 '텍스트 줄 바꿈' 속성이 설정되어야 하므로

원하는 셀에 same css를 설정하여 같은 셀에 표시할 수 있도록 해준다.



4. 숫자 형식 지정(자릿점 표시)

원하는 셀에 다음과 같이 스타일을 지정한다.


//number가 문자열인 경우에도 강제 지정

Response.Write(string.Format(@"<td style=""mso-number-format:'#,###';"">{0}</td>", number));


또는 


//number가 숫자형식인 경우만 제대로 표시

Response.Write(string.Format("<td>{0:N0}"</td>, number));



5. 강제 문자열 형식 지정(숫자도 문자처럼 표시)


Response.Write(string.Format(@"<td style=""mso-number-format:'@';"">{0}</td>", string));



6. 한글 인코딩 설정


Response.Charset = "UTF-8";

Response.ContentEncoding = System.Text.Encoding.GetEncoding("utf-8");


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의 멤버들이 표시된다.