드레그 와 드롭은 일상에서 많이 사용하고 있다. 근데 개발툴에서는 많이 사용하지 않았지만 앞으로 개발툴도 이러한 기능으로 소스코딩양을 줄여주는것이 좋을것 같다.
이기능은 사용하려면 드래그 하는 곳과 드롭하는 곳에 상호작용 및 순서가 필요하다.
드래그소스->드롭타깃->드롭효과->트랜스
먼저 드레그 클래스 계층도를 살펴보자
ㅁ 드레그 소스
드레그 소스에는 여러가지 형태가 있을수 있다
가령 text, file, 워드와 같이 특정 문자에 색이나 강조등의 효과를 가지고 있는 RTP 형식 문서등이 있다.
여기서는 해당소스가 명칭을TextTransfer, FileTransfer,HTML Transfer,RTF Transfer 라 하고 각각
instance를 생성 전달하게 된다.
여기서 간단한 예제로 Label에 소스를 드레그해서 이클립스 java editer에 드롭하면 move되는 소스를 참고 하여보자
package swt.drag_drop;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
public class DragSourceTest {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
shell.setText("SWT DragSource Test");
// 레이블 위젯을 드래그 원본(Drag Source)으로 활성화 한다.
final Label label = new Label(shell, SWT.BORDER);
label.setText("text to be transferred");
int operations = DND.DROP_MOVE | DND.DROP_COPY;
DragSource source = new DragSource(label, operations);
// 텍스트 포맷 내에 데이터를 제공한다.
Transfer[] types = new Transfer[]{TextTransfer.getInstance()};
source.setTransfer(types);
source.addDragListener(new DragSourceListener() {
public void dragStart(DragSourceEvent event) {
// 레이블 내에 실제 텍스트가 있을 경우에만, 드래그를 시작한다.
if (label.getText().length() == 0) {
event.doit = false;
}
}
public void dragSetData(DragSourceEvent event) {
// 요청된 타입의 데이터를 제공한다.
if (TextTransfer.getInstance().isSupportedType(event.dataType)) {
event.data = label.getText();
}
}
public void dragFinished(DragSourceEvent event) {
// 만약, 데이터의 이동(MOVE) 작업이 수행되었다면,
// 드래그 원본인 레이블 위젯에서 이동한 데이터를 제거한다.
if (event.detail == DND.DROP_MOVE) {
label.setText("");
}
}
});
shell.setSize(640, 480);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
구현시 처리되는동영상을 참고하세요
Drag 처리
ㅁ 드롭 타겟
다음은 드롭소스를 예제로 생성해 보았다 반대로 드레그는 이클립스에 자바소스에서 드롭은 개발된 소스에서 받는걸로 예제를 처리했다.
package swt.drag_drop;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
public class DropTargetCopyTextFileTest {
private static void open(Text text, String filename) {
File file = new File(filename);
try {
text.setText("");
FileReader reader = new FileReader(file);
BufferedReader in = new BufferedReader(reader);
String str = null;
while ((str = in.readLine()) != null) {
text.append(str + "\n");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
shell.setText("SWT DropTarget Test");
final Text text = new Text(shell, SWT.BORDER | SWT.MULTI);
int operations = DND.DROP_DEFAULT | DND.DROP_COPY | DND.DROP_MOVE;
DropTarget target = new DropTarget(text, operations);
target.setTransfer(new Transfer[]{FileTransfer.getInstance(),
TextTransfer.getInstance()});
target.addDropListener(new DropTargetAdapter() {
FileTransfer fileTransfer = FileTransfer.getInstance();
TextTransfer textTransfer = TextTransfer.getInstance();
public void dragEnter(DropTargetEvent e) {
System.out.println("[dragEnter] e : " + e);
TransferData data[] = e.dataTypes;
for (int i = 0; i < data.length; i++) {
System.out.println("[dragEnter] data[" + i + "] : "
+ data[i]);
}
if (e.detail == DND.DROP_DEFAULT) {
e.detail = DND.DROP_COPY;
}
}
public void dragOperationChanged(DropTargetEvent e) {
if (e.detail == DND.DROP_DEFAULT) {
e.detail = DND.DROP_COPY;
}
}
public void drop(DropTargetEvent e) {
System.out.println("[drop] e : " + e);
if (fileTransfer.isSupportedType(e.currentDataType)) {
String[] files = (String[]) e.data;
if (files != null && files.length > 0) {
open(text, files[0]); // 파일을 연다
}
}
if (textTransfer.isSupportedType(e.currentDataType)) {
String str = (String) e.data;
if (str != null) {
text.setText(str); // 텍스트를 커서 위치에 삽입
}
}
}
});
// shell.setLocation(display.getBounds().width - 320,
// display.getBounds().height - 240);
shell.setSize(320, 240);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
여기도 동영상을 보면 어떻게 구현했는지를 알수 있다.
Drop
ㅁ 사용자 포멧 드레그 엔 드롭
개발하다보면 사용자 포멧에 데이터를 드레그 엔 드롭을 하고 싶을때가 있다
▶ MySimpleDragAndDrop에서 화면구성 및Drag소스를MyType으로Table에TableItem 객체로 구성
<Context>
<Resource
maxWait="-1"
maxIdle="10"
maxActive="20"
username="[아이디]"
password="[패스워드]"
url="jdbc:mysql://[ip]:3307/work"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
auth="Container"
name="jdbc/MyBoard1"/>
<!--
auth : 컨테이너를 자원 관리자로 기술
name : JDBC이름, 변경 가능
driverClassName : JDBC 드라이버
type : 웹에서 이 리소스를 사용할 때 DataSource로 리턴됨
username : 접속계정
password : 접속할 계정 비밀번호
loginTimeout : 연결 끊어지는 시간
maxActive : 최대 연결 가능한 Connection수 (기본 20개)
maxIdle : Connection pool 유지를 위해 최대 대기 connection 숫자
maxWait : 사용 가능한 커넥션이 없을 때 커넥션 회수를 기다리는 시간 (1000 = 1초)
testOnBorrow : db에 test를 해볼 것인지
-->
</Context>
<%@ page import="javax.naming.*, javax.sql.*, java.sql.*"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
Connection con = null;
PreparedStatement stmt = null;
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
//resource명과 res-ref-name과 일치하는 이름
DataSource ds = (DataSource) envCtx.lookup("jdbc/MyBoard1");
con = ds.getConnection();
String msg = "disconnection";
if (con != null) {
msg = "connection";
}
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>
Results =
<%=msg%></h2>
</body>
</html>
▶ 자바사용
package com.board.dicws.lib;
import java.sql.Connection;
import java.sql.SQLException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
public class DBConnection {
public static Connection getConnection() throws SQLException, NamingException, ClassNotFoundException {
Context initCtx = new InitialContext();
// initCtx의 lookup메서드를 이용해서 "java:comp/env" 에 해당하는 객체를 찾아서 evnCtx에 삽입
Context envCtx = (Context) initCtx.lookup("java:comp/env");
// envCtx의 lookup메서드를 이용해서 "jdbc/MyBoard1"에 해당하는 객체를 찾아서 ds에 삽입
DataSource ds = (DataSource) envCtx.lookup("jdbc/MyBoard1");
// getConnection메서드를 이용해서 커넥션 풀로 부터 커넥션 객체를 얻어내어 conn변수에 저장
Connection conn = ds.getConnection();
return conn;
/*
* 위의 코드를 아래와 같이 줄여서 작성 가능하다. Context context = new InitialContext(); DataSource
* dataSource = (DataSource) context.lookup("java:comp/env/jdbc/oracle");
* Connection con = dataSource.getConnection();
*
*/
}
}
2) server.xml과 context.xml을 이용한 연결
1-1) DBCP 정보설정
server.xml 편집 : GlobalNamingResources 테그에 Resource 추가
<GlobalNamingResources>
<!-- Editable user database that can also be used by
UserDatabaseRealm to authenticate users
-->
<Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
<Resource
maxWait="-1"
maxIdle="10"
maxActive="20"
username="[아이디]"
password="[패스워드]"
url="jdbc:mysql://[ip]:3307/work"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
auth="Container"
name="jdbc/MyBoard1"/>
<!--
auth : 컨테이너를 자원 관리자로 기술
name : JDBC이름, 변경 가능
driverClassName : JDBC 드라이버
type : 웹에서 이 리소스를 사용할 때 DataSource로 리턴됨
username : 접속계정
password : 접속할 계정 비밀번호
loginTimeout : 연결 끊어지는 시간
maxActive : 최대 연결 가능한 Connection수 (기본 20개)
maxIdle : Connection pool 유지를 위해 최대 대기 connection 숫자
maxWait : 사용 가능한 커넥션이 없을 때 커넥션 회수를 기다리는 시간 (1000 = 1초)
testOnBorrow : db에 test를 해볼 것인지
-->
</GlobalNamingResources>
사이트에서 일하다보면 엑셀로 무수히 많은 엑셀자료를 만들기는 하는데 이걸 참조해서 개발하는 개발자는 너무많은 자료에 치여사는경우가 많다 그래서 생각한것이 하나의 만들어놓은 엑셀에서 관련되어 있는 엑셀을 query를 실행하여 조회하는 메크로를 작성해보았다
전에 Database를 사용하기 위해서는 ODBC드라이버가 있어야된다고 했는데 ODBC드라이버를 확인해보자
1) ODBC설치 확인(기본으로 OFFICE를 설치하면 설치된는것을 알수 있다)
2) 참조에 Microsoft ActiveX DataObject 2.8 Library를 추가 : ADODB 객체를 사용하려구
3) 일단 엑셀을 sql로 조회하기 위한 엑셀을 하나 준비한다
4) 엑셀을 DataBase처럼 Connection을 실행해서 잘 연결되는지 확인해보자
특이하게 Provider를 사용하여 쓰고 뒤에 Properties가 더 붙는다
Public dbcon As ADODB.Connection
Public dbcon As ADODB.Connection
Public Sub ExcelCon() '=>실행시 문제가 없는지 확인
Dim strCon As String '연결String
Dim driver, dsrc
dsrc = "D:\엑셀DB테스트.xlsx" '파일명
'엑셀파일을 DataBase처럼 연결
strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & dsrc & ";Extended Properties=Excel 12.0;"
Set dbcon = New ADODB.Connection
dbcon.Open strCon '연결
End Sub
5) 연결이 잘되었으면 RecordSet으로 받아 엑셀에 출력을 해보자
Public Sub getExcelEtcSel()
Dim rs, sql, colCnt, wRow, i
ExcelCon
sql = "select * from [Sheet2$] " '->조건없이 전부 조회
Debug.Print sql
'Set rs = CreateObject("ADODB.RecordSet")
Set rs = New ADODB.Recordset
rs.Open sql, dbcon
wRow = ActiveSheet.Range("B4") '작성시작 row
colCnt = rs.Fields.Count
'컬럼에 head를 시작에 달아줌
For i = 0 To colCnt - 1
ActiveSheet.Cells(wRow, i + 1) = rs.Fields(i).Name
Next
setHeaderStyle wRow 'header 스타일 적용
wRow = wRow + 1
If rs.EOF = False Then
Do While rs.EOF = False
For i = 0 To colCnt - 1
ActiveSheet.Cells(wRow, i + 1) = rs(rs.Fields(i).Name) '레코드셋에 이름으로 매핑하여 표시
Next
wRow = wRow + 1
rs.MoveNext
Loop
End If
End Sub
6) 엑셀에 특정영역중에 query를 사용할경우와 컬럼명을 기술할때 일반 query와 상이함
sql = "select [컬럼1],[컬럼2] from [Sheet2$A2:G5] "
- 시트전체조회시 [시트명$]
- 시트에일부영역시 [Sheet2$A2:G5] -> sheet2에 A2:G5 영역중 조회
- 컬럼은 위처럼 중괄호를 해야되고 중복된 컬럼명이 있으면 임의로 넘버링을 붙임
단독적으로 쓸일은 많지는 않았다 그보다 현재 많은 정보들이 있다보니 각종 소스들에 대해서 목록으로 처리해야될일이 많아졌다 생각 되어진다.
프로젝트에서 말하자면 현황파악
제일먼저 특정경로에 소스를 가져왔을때 해당 소스하위까지 포함하여 폴더에 목록을 엑셀로 작성해보자
1) 엑셀시트 화면 구성
B1에는 검색하려는 기본경로 기입
B2에는 기존 목록을 삭제하고 다시 작성할건지 여부
B3에는 전체작성된 건수를 엑셀함수를 써서 기입=COUNT(A9:A1048576)
2) 소스작성
먼저 파일을 사용하기 위해 참조를 하자
직접 CreationObject를 사용하여도 되지만 ctrl+space로 자동완성기능을 사용하기 위하여
참조를 통하여 객체를 넣는 작업을 한다
다음은 엑셀 코딩을 하자
Option Explicit '명시적으로 항상 어떤변수를 사용했는지 확인하는게 신상에좋다
Dim wRow '파일을 엑셀시트에 저장하기 위해 선언==> 말하자면 전역변수선언
Public Sub getFileList() '==>실행하는 함수
Dim rc
wRow = 9 '기본은 9부터
If ActiveSheet.Range("B2") = "Y" Then '삭제여부를 보고 삭제작업
rc = MsgBox("삭제해도 될까요?", vbYesNo, "삭제경고")
If rc = vbYes Then
Rows(wRow & ":" & wRow).Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Delete Shift:=xlUp
Else
Exit Sub
End If
'타이틀을 작성한다
ActiveSheet.Cells(wRow, 1) = "NO"
ActiveSheet.Cells(wRow, 2) = "파일명"
ActiveSheet.Cells(wRow, 3) = "경로"
ActiveSheet.Cells(wRow, 4) = "타입"
ActiveSheet.Cells(wRow, 5) = "Size"
ActiveSheet.Cells(wRow, 6) = "비고"
'이건별도 나만에 함수로 생략 setHeaderStyle wRow 'header 스타일 적용
wRow = wRow + 1
Else
wRow = ActiveSheet.Range("B3") + 10 '삭제를 안하고 추가하는경우 헤더포함하여 다음써야될행
End If
'b1에 입력된 기본 경로하위 폴더 및 파일목록을 작성시작
FolderFile ActiveSheet.Range("B1")
End Sub
Function FolderFile(fn As String)
Dim fs As FileSystemObject
Set fs = New FileSystemObject
Dim foldeer As Folder
Dim fileinfo
Dim Filnavn() As String
Set foldeer = fs.GetFolder(fn)
'해당폴더에 파일이 있는경우
For Each fileinfo In foldeer.Files
ActiveSheet.Cells(wRow, 1) = wRow - 9 '기본자릿수
ActiveSheet.Cells(wRow, 2) = fileinfo.Name '파일명
ActiveSheet.Cells(wRow, 3) = Mid(fileinfo.path, 1, Len(fileinfo.path) - Len(fileinfo.Name)) 'path에 파일명까지 같이 들어오므로 파일명 길이만큼 잘라path만입력
ActiveSheet.Cells(wRow, 4) = fileinfo.Type
ActiveSheet.Cells(wRow, 5) = fileinfo.Size
wRow = wRow + 1 '작성후 다음위치 + 1
Debug.Print "F " & fileinfo
Next
For Each Folder In foldeer.SubFolders 'sub폴더가 있는경우
Debug.Print "D " & Folder
FolderFile (Folder) '재귀함수로 자신을 다시 부름
Next
End Function
파일처리 목록완성 예시
3) 하이퍼링크를 활용하여 클릭시 자동열리게 하자
요즘은 하도 참조하는 문서가 많아 헷갈리는경우가 많다 저같은경우 목록을 작성하고
뒤에 비고란에 확인한 내용 및 주요 참고내용등을 적어놓고 다시 열때는 클리하여 자동열기를 주로 사용하고 있다
▶ root계정로그인
$mysql -u root -p
Enter password:[패스워드]
※ Mysql(MariaDB동일)은 command나 Sql툴로 접근 command같은 내용이 처리됨
▶ 계정관련
select host, user, password from user; :조회
create user [계정아이디]@'[접속지제한]' identified by '비밀번호'; :생성
※ 접속지제한 % : 전체, localhost : 해당서버만, ip인경우 특정 ip 에서만 접근제어
※ 접속지제한에 싱글따옴표 필수, MariaDB는 패스워드 정책에 따라 10글자 필수
다른 방법으로는
INSERT INTO user (Host, User, Password) VALUES ('localhost', '계정아이디', password('비밀번호'));
FLUSH privileges;
delete from user where user='[계정아이디]';
다른 방법으로는
drop user '사용자ID'@localhost;
ㅁ 데이터베이스 관리(생성,권한, 권한반영)
▶ DataBase변경
use mysql
※ command 모드에만 적용
▶ DataBase(스키마) 관리
show databases; : 조회
create schema DB명; : 생성
옵션예) create database DB명 default character set utf8;
drop database DB명; : 삭제
▶ 설정변경에 대한 반영 command
flush privileges
ㅁ 테이블 관리
▶ 테이블 관련
- database 테이블조회
show tables;
- 권한 추가: localhost접속시만 처리가능
grant all privileges on '스키마명'.'테이블명' to '계정명'@'호스트' identified by '계정비밀번호' with grant option;
※스키마명.* 는 해당 스키마에 전부
- 권한조회
show grants for '계정명'@'호스트';
- 권한 삭제
revoke all on '스키마명'.'테이블명' from '계정명'@'호스트';
▶ primary key 관리
alter table 테이블명 drop primary key;
alter table 테이블명 add primary key(컬럼명, 컬럼명);
ㅁ 테이블 조회
SELECT
TABLE_SCHEMA 스키마
,TABLE_NAME 테이블영문명
,TABLE_COMMENT 테이블한글명
,TABLE_TYPE 테이블타입
,TABLE_COLLATION 테이블구조
,TABLE_ROWS 레코드건수
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA like '${schema}%'
AND (TABLE_NAME LIKE '${var}'
OR TABLE_COMMENT LIKE '${var}')"
스키마명, 테이블명(한글)
ㅁ 컬럼조회
SELECT ORDINAL_POSITION AS NO
, (CASE WHEN COLUMN_KEY !='' THEN 'Y'
ELSE '' END) PK
, COLUMN_NAME 영문명
, COLUMN_COMMENT 한글명
,IS_NULLABLE AS NULLYN
, DATA_TYPE 데이터타입
, (case when DATA_TYPE='int'
then NUMERIC_PRECISION
else CHARACTER_MAXIMUM_LENGTH end) 자릿수
, NUMERIC_SCALE 소수점
, ' ' 데이터
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA= '{$schema}'
AND TABLE_NAME = '${var}'
ORDER BY ORDINAL_POSITION"
SQL>SELECT TABLESPACE_NAME, STATUS, CONTENTS FROM DBA_TABLESPACES; : 테이블스페이스 목록
SQL>SELECT FILE_NAME, BYTES, STATUS FROM DBA_DATA_FILES; :테이블스페이스 파일 목록
SQL>SELECT TABLESPACE_NAME, BYTES, BLOCKS FROM DBA_FREE_SPACE; :테이블스페이스 잔여 공간
ㅁ 테이블스페이스 생성/삭제 권한설정
SQL>CREATE TABLESPACE work DATAFILE 'work.dat' SIZE 50M AUTOEXTEND ON NEXT 10M; : tablespace 생성
SQL>ALTER USER [계정명] DEFAULT TABLESPACE work; : user tablespace 할당
SQL>DROP TABLESPACE work INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS; : tablespace 삭제
※ 테이블스페이스명 work