엑셀 데이터를 DB에 집어넣기 위한 자료 만들어보는 방법이다.


먼저 테이블 구조를 살펴보자.

네이버지식인에서 문의한 테이블 구조를 가지고 작성한다.

CREATE TABLE IF NOT EXISTS `test` (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `id` varchar(20) NOT NULL,
  `count` int(11) NOT NULL,
  `state` varchar(10) NOT NULL,
  PRIMARY KEY (`uid`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;


테이블에 데이터를 Insert 하는 쿼리문을 작성한다.

INSERT INTO test (id, count, state) VALUES ('test1', 6, 'a');


uid 칼럼은 자동 증가칼럼이므로 생략해도 된다.

만약 에러가 난다면

INSERT INTO test (uid, id, count, state) VALUES (NULL, 'test1', 6, 'a');

로 해주면 된다.


엑셀에서 쿼리문을 만들려면

=CONCATENATE("INSERT INTO test (id, count, state) VALUES ('",A3,"', ",B3,", '",C3,"');")

와 같은 Query 문을 만든다.



값이 들어있는 만큼 Drag 값을 채워나간다.



그런 다음에, EditPlus 같은 텍스트 에디터를 이용하여 결과값을 복사하여 EditPlus 에 복사해서 쿼리문을 확인한다.


phpMyAdmin 에서 SQL 에 쿼리문을 붙여넣기하고 실행한다.

또는 MySQL 에 직접 접속하여 붙여넣기를 한다.


테스트에 사용한 엑셀 파일

Excel_Query_make.xlsx






728x90

'SQL' 카테고리의 다른 글

[MySQL] 칼럼명 변경, 추가, 삭제  (0) 2016.10.26
[MySQL] SQL 모음  (0) 2016.09.23
조건별 SUM SQL  (0) 2016.07.27
[MySQL] Self Join 예제  (0) 2016.02.22
[MySQL] order by 정렬  (0) 2016.01.26
블로그 이미지

Link2Me

,

// DB Query Cutom 함수
function getDbData($table,$where,$data,$orderby){
    global $db;
    $result = mysql_query('select '.$data.' from '.$table.($where?' where '.getSqlFilter($where):'').($orderby?' order by '.getSqlFilter($orderby):''));
    $row = mysql_fetch_array($result);
    return $row;
}

//SQL필터링
function getSqlFilter($sql){
    return $sql;
}


함수를 만들어서 사용할 경우 제대로 잘 만들어졌는지 테스트 하는 과정은 아래과정으로 진행했다.

sql 쿼리문을 화면상에 나오게 하여 제대로 나왔는지 확인했다.


<?php
$table ='MEMBER';
$part1CD='04';
$part2CD='23';
$part3CD='00';
$partNM = '기타';
$where ="part1CD='".$part1CD."' and part2CD='".$part2CD."' and part4CD='00' and partNM='".$partNM."'";
$data ='*';
$orderby = 'idx DESC';
//$orderby = '';

$sql = 'select '.$data.' from '.$table.($where?' where '.getSqlFilter($where):'').($orderby?' order by '.getSqlFilter($orderby):'');
echo $sql;

function getSqlFilter($sql)
{
    return $sql;
    // preg_replace("/찾을 문자열/" , "변경할 문자열" , "해당 문자열");
    // /찾을 문자열/ 에서 / 는 정규식의 시작과 끝을 알린다.
    //return preg_replace("( union| update| insert| delete| drop|\/\*|\*\/|\\\|\;)",'',$sql);
}

?>

728x90
블로그 이미지

Link2Me

,

소스에 deprecated 라고 나오는 부분이다.



AlertDialog alertDialog = new AlertDialog.Builder(Login.this).create();
    alertDialog.setTitle("네트워크 연결 오류");
    alertDialog.setMessage("사용가능한 무선네트워크가 없습니다.\n" +
                           "먼저 무선네트워크를 확인해 주세요.");
    alertDialog.setCancelable(false);
    alertDialog.setIcon(R.drawable.icon_dialog);
    alertDialog.setButton("확인", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
            finish();
            //application 프로세스를 강제 종료
            android.os.Process.killProcess(android.os.Process.myPid() );
                                           
        }
    });
    alertDialog.show();



아래와 같이 수정하면 된다.


AlertDialog.Builder builder = new AlertDialog.Builder(Login.this);
    builder.setTitle("네트워크 연결 오류")
    .setMessage("사용가능한 무선네트워크가 없습니다.\n" +
                "먼저 무선네트워크를 확인해 주세요.")
    .setCancelable(false)
    .setIcon(R.drawable.icon_dialog)
    .setNegativeButton("확인",new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
            finish();
            //application 프로세스를 강제 종료
            android.os.Process.killProcess(android.os.Process.myPid());
        }
    });
    AlertDialog alert = builder.create();
    alert.show();




728x90
블로그 이미지

Link2Me

,

조건별 SUM SQL

SQL 2016. 7. 27. 17:18

네이버지식인에 올라온 질문사항이 있어서 테스트 해보고 올려둔다.


1. 테이블 생성

CREATE TABLE IF NOT EXISTS `test` (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `id` varchar(20) NOT NULL,
  `count` int(11) NOT NULL,
  `state` varchar(10) NOT NULL,
  PRIMARY KEY (`uid`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ;

INSERT INTO `test` (`uid`, `id`, `count`, `state`) VALUES
(1, 'test1', 6, 'a'),
(2, 'test2', 6, 'a'),
(3, 'test1', -1, 'b'),
(4, 'test2', -2, 'b'),
(5, 'test2', -1, 'b'),
(6, 'test3', 5, 'a'),
(7, 'test3', 2, 'a'),
(8, 'test3', -3, 'b');


2. 쿼리문 작성

   쿼리문은 phpMyAdmin 에서 하면 편하고 좋다.

원하는 결과를 얻기 위해 하나씩 쿼리문을 입력하면서 확인한다.

SELECT id, sum(count), state FROM test group by id;
SELECT id, sum(count), state FROM test where state='a' group by id;
SELECT id, sum(count), state FROM test where state='b' group by id;


그런 다음에 실제 구하려는 쿼리문을 작성한다.

SELECT id, sum(case when state='a' then count else 0 end) as a_count, sum(case when state='b' then count else 0 end) as b_count FROM test group by id;


또는

SELECT id, sum(if(state='a', count, 0)) as a_count, sum(if(state='b', count, 0)) as b_count FROM test group by id;


자료를 검색해서 찾는 방법

구글에서 검색어 sql sum if condition 를 입력하고 자료를 찾으면 내가 원하는 걸 찾아볼 수 있다.


키포인트는 sum 인데 조건 sum 인거다. 그러므로 조건이 들어가는 sum 과 if 를 검색해보면 된다.


CASE WHEN 은 http://link2me.tistory.com/516 참조하면 된다. 하지만 이해가 부족할 수 있다. 구글링으로 게시글 읽어보고 원하는 걸 얻으면 된다.



728x90

'SQL' 카테고리의 다른 글

[MySQL] SQL 모음  (0) 2016.09.23
엑셀에서 INSERT 쿼리문 만들기  (0) 2016.07.29
[MySQL] Self Join 예제  (0) 2016.02.22
[MySQL] order by 정렬  (0) 2016.01.26
MySQL Update Where 조건절 Subquery  (1) 2016.01.22
블로그 이미지

Link2Me

,

파일을 업로드하는 코딩시 고려할 사항이다.


파일을 업로드시에 공격이 성공하면 바로 서버가 해킹되는 것이기 때문에 가장 리스크가 큰 취약점이다.

보안(Security)을 고려하고 실행파일이 업로드되지 않도록 해야 한다.

먼저, 파일 업로드 기능이 있는 페이지를 전부 조사해서 WebShell 같은 악의적인 파일이 업로드될 수 있는지 체크해야 한다.


1. 파일 업로드시 확장자 검사 루틴

    - 기본적으로는 Apache 환경설정에서 mine type 필터링을 설정한다.

      Apache 환경설정 http://link2me.tistory.com/426  http://link2me.tistory.com/991 참조

    <IfModule mime_module>
        TypesConfig conf/mime.types
        AddType application/x-compress .Z
        AddType application/x-gzip .gz .tgz
        AddType application/x-httpd-php .php .html
        AddType application/x-httpd-php-source .phps
    </IfModule>


   - 하지만 공격자가 Proxy-Server 등을 통해 우회할 수 있으므로 확장자 필터링을 적용한다.

     업로드가 허용된 확장자만 업로드가 가능하도록 서버 필터링을 하여야 한다.

 

2. 파일명은 치환(난수화)해서 저장한다.
    그리고 파일 접근권한을 읽기 전용모드로 등록한다. (실행권한 부여 금지)


3. 등록시 변경 파일명을 DB에 저장한다.

    - 게시판에 첨부되는 파일명인 경우, 변경 파일명을 DB 테이블에 기록하여 찾을 수 있도록 한다.


4. 가능하면 파일 업로드 장소를 물리적으로 분리한다.

    물리적으로 분리하지 않은 경우라면 해당 디렉토리가 어디인지 알수 없게 다른 곳으로 지정한다.


파일 업로드시 제한 용량은 php.ini 파일에 설정되어 있다.

업로드 용량을 많이 설정하려면 php.ini 파일을 수정하고 Apache 를 restart 해야 한다.

; PHP 가 받아들이는 POST data 최대 크기
; default 8M 로 되어 있음, upload_max_filesize 보다 크게 설정해야 함
post_max_size = 20M
memory_limit = 128M
upload_max_filesize = 19M


// 테이블 구조 예시

CREATE TABLE IF NOT EXISTS file_upload (
  uid int(11) NOT NULL AUTO_INCREMENT,
  folder varchar(10) NOT NULL DEFAULT '',
  name varchar(250) NOT NULL DEFAULT '',
  size int(11) NOT NULL DEFAULT '0',
  d_regis varchar(14) NOT NULL DEFAULT '',
  PRIMARY KEY (uid),
  KEY d_regis (d_regis)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;


//파일을 전송하는 PHP 소스 부분

파일명을 excel 로 사용했으면 받는 쪽에서도 excel 로 사용해야 한다.

보통은 userfile 이라고 많이 쓴다.

<form enctype="multipart/form-data" action="fileupload.php" method="POST">
 <input 
type="file" name="excel"  />

 <input type="submit" value="upload" />
</form>



// 파일을 전송받은 PHP 소스 부분

여러개의 확장자를 검사하려면 strstr('[csv]',$fileExt) 부분을 수정하면 된다.

strstr('[csv,php,html,htm,inc,do]',$fileExt) 와 같이 확장자 여러개를 나열해준다.


<?php
    // Edit upload location here
    $tmpname    = $_FILES['excel']['tmp_name'];
    $realname    = $_FILES['excel']['name'];
    $fileExt    = getExt($realname);  // 확장자 필터링을 위한 확장자 추출
    $destination_path='uploads/';
    $rndname = hash('sha256', $realname).date("Ymd").'.'.$fileExt;  // 파일명 hash 처리
    $readFile = $destination_path . $rndname;

    if (is_uploaded_file($tmpname)) {
        if (!strstr('[csv]',$fileExt)) {  // 확장자 필터링 검사
            echo '<script type="text/javascript">alert("csv 파일만 등록할 수 있습니다.");</script>';
            exit;
        }
        move_uploaded_file($tmpname,$readFile);
        @chmod($readFile,0404);  // 파일 권한을 읽기모드로 설정

    }

    function getExt($filename){
        $ext = substr(strrchr($filename,"."),1); // 뒤에서부터 콤마 위치로부터 가져오기
        $ext = strtolower($ext); // 소문자로 강제치환
        return $ext;
    }

    ?>



아래 코드는 업로드시 파일명을 치환하는 연습 코드이다.


<?php
//$realname = strtolower($_FILES['excel']['name']);
$realname = 'shell.asp;.jpg';
$fileExt = getExt($realname);
//$tmpname = md5($realname).date("Ymd").'.'.$fileExt;
$tmpname = hash('sha256', $realname).date("Ymd").'.'.$fileExt;

echo $tmpname;
echo '<br />';
echo strlen($tmpname);

function getExt($filename){
    $ext = substr(strrchr($filename,"."),1); // 뒤에서부터 콤마 위치로부터 가져오기
    $ext = strtolower($ext); // 소문자로 강제치환
    return $ext;
}

?>


파일을 2개 업로드하는 걸 고려한다면

<form enctype="multipart/form-data" action="fileupload.php" method="POST">

이미지 파일1 <input type="file" name="imagefile[]">

이미지 파일2 <input type="file" name="imagefile[]">

<input type="submit" value="upload" />

</form>


fileupload.php 에서 확인해 볼 사항

echo '<pre>', print_r($_FILES) ,"</pre>";

$_FILES['imagefile']['name'][0];

$_FILES['imagefile']['name'][1];

$_FILES['imagefile']['type'][0];

$_FILES['imagefile']['type'][1];

$_FILES['imagefile']['tmp_name'][0];

$_FILES['imagefile']['tmp_name'][1];

$_FILES['imagefile']['size'][0];

$_FILES['imagefile']['size'][1];

$_FILES['imagefile']['error'][0];

$_FILES['imagefile']['error'][1];


참조하면 도움되는 게시글

http://blog.habonyphp.com/entry/php-POST-%ED%8C%8C%EC%9D%BC-%EC%97%85%EB%A1%9C%EB%93%9C#.V5RntaKzHpU


jQuery PHP 파일 업로드 게시글 : http://link2me.tistory.com/1142


Ajax PHP 파일 업로드 게시글 : http://link2me.tistory.com/1143

728x90
블로그 이미지

Link2Me

,

eclipse 가 실행되어 있는 걸 깜빡하고 eclipse 버튼을 또 누르면 workspace1 을 새로 생성할거냐고 물어본다. 아무 생각없이 Yes 를 누르면 완전 새로운 화면이 뜨면서 그동안 작성했던 내용은 하나도 안보인다. ㅠㅠㅠ


몇번의 시행착오를 거치고 나서야 workspace 를 변경해서 사용할 수 있다는 걸 알았다.

workspace1 을 새로 생성하면 모든 환경설정 상태가 초기화가 되어 버린다.


workspace_work 폴더를 수동으로 생성한 다음에 workspace 에 있는 파일 전부를 workspace_work 로 복사를 한다.

workspace 를 변경해서 해당 폴더를 선택한다.

그러면 원래 workspace 에서 저장했던 모든 환경설정 정보가 그대로 남아 있다.


workspace 를 변경하는 방법은 간단하다. 아래 그림처럼 해주기만 하면 된다.



여기서 중요한 점!!!!

폴더채 복사를 했기 때문에 환경설정 정보가 기존 폴더 정보를 가리키고 있을 수도 있다.

혹시나 하고 삭제를 했더니 workspace_work 폴더에 있는 프로젝트 파일이 삭제되는게 아니라 workspace 에 있는 프로젝트 파일이 삭제되는 걸 경험했다.

그러므로 열린 파일을 하나하나 모두 닫아준다.




프로젝트 파일 삭제를 선택하지 않고 그냥 OK를 눌러서 프로젝트만 삭제한다.

해당 폴더 workspace_work 에서 수동으로 불필요한 파일을 전부 삭제한다.

불필요한 파일이란 workspace 에는 있어야 하고 workspace_work 에는 없어야 하는 파일이다.


이렇게 프로젝트를 전부 닫은 상태에서 프로젝트를 다시 열기를 하면 된다.



폴더별로 원하는 형태로 관리를 하면 편리한 거 같다.

기존에는 이걸 몰라서 업무용 프로젝트와 연습하는 프로젝트를 같이 혼용해서 사용했었다.


개발을 하다보면 다른 폴더에 구분해 놓은 프로젝트를 참조할 경우가 생긴다.

그러면 해당 프로젝트를 import 로 읽어들이면 된다. (http://link2me.tistory.com/1021)

728x90
블로그 이미지

Link2Me

,

안드로이드 애플리케이션은 크게 '자바코드'와 '리소스'로 구성된다.

자바코드는 애플리케이션의 흐름과 기능을 정의하는 부분이고

리소스는 Layout 이나 이미지와 같이 주로 애플리케이션이 사용자에게 보이는 부분이다.

Manifest는 설치된 애플리케이션의 구성요소나 권한을 정의한다.


Layout 은 ViewGroup 클래스로부터 상속을 받으며, Layout 안에 존재하는 위젯(버튼, 텍스트뷰,에디트뷰 등)을 배치한다. 화면에 구성하려면 Layout 에 대해 이해를 해야 한다.

스마트폰의 크기가 다양하므로 절대 픽셀 위주로 Layout을 잡는 것은 대단히 위험하다.

그래서 본 내용에서는 절대 Layout 은 다루지 않는다.


 공통

 android:layout_width="match_parent" // 무조건 남아있는 여유공간을 채움
 android:layout_width="wrap_content" // View의 내용물의 크기에 따라 결정되도록 함
 android:layout_margin="10dp"  // 위젯과 여유 공간 사이의 여백 설정
 android:padding="20dp"  // 위젯 내부 여백 설정

LinearLayout

 간단하고 직관적으로 이해하기 쉬워서 많아 사용한다.

 자식(child) View 들을 수평 또는 수직으로 배치한다.

 android:orientation="vertical"  // 수직으로 배치(수직으로 차곡차곡 쌓겠다)

 android:gravity="top" // 상단 (View의 정렬방향을 설정)

 android:gravity="left|top" // 왼쪽 상단

 android:gravity="center_horizontal|center_vertical"  // 정중앙

 android:gravity="right|bottom"  // 오른쪽 하단

 Gravity 속성을 이용하여 자식(child) View 를 상단, 하단, 중앙에 배치할 수 있다.

 android:layout_weight="1" // View 내부 child끼리의 크기 비율 지정(공간 가중치) 

 child View 의 가중치를 지정하지 않으면 0 으로 간주하고 확장하지 않는다.

 LinearLayout 을 여러개 사용하면 각 Layout의 크기를 지정해야 한다.

 내부 LinearLayout 에서 layout_weight="1" 로 모두 지정하면 비율이 동일하게 출력된다.

 layout_margin은 "값"만큼 띄어서 배치하겠다는 뜻

 android:layout_gravity=center

 gravity 속성 앞에 layout이 붙어 있으면 해당 위젯이 포함되어 있는 Layout 위젯의

 정렬방식을 의미한다.

 

 RelativeLayout

 View 들의 위치가 상대적으로 정해진다.

 (기준 View 가 있고, 배치하고자 하는 View를 기준 View의 어디에 둘 것인지 설정)

 RelavtiveLayout 은 자신을 포함하고 있는 컨테이너나 다른 위젯을 기준으로 위젯을

 배치하는 레이아웃(layout)이다.

 부모 컨테이너나 다른 View(위젯)와의 상대적 위치를 이용해 화면을 구성한다.

 android:layout_below="@id/topButton"  <-- topButton 기준으로 하단에 위치

 android:layout_above="@id/bottomButton" <-- bottomButton 기준 위에 위치


  자신을 포함하는 컨테이너를 기준으로 해당 위젯을 배치하는 속성들

 layout_alignParentTop : 부모 컨테이너의 위쪽과 뷰의 위쪽을 맞춤
 layout_alignParentBottom : 부모 컨테이너의 아래쪽과 뷰의 아래쪽을 맞춤
 layout_alignParentLeft : 부모 컨테이너의 왼쪽 끝과 뷰의 왼쪽 끝을 맞춤
 layout_alignParentRight : 부모 컨테이너의 오른쪽 끝과 뷰의 오른쪽 끝을 맞춤
 layout_centerHorizontal : 부모 컨테이너의 수평방향 중앙에 배치
 layout_centerVertical : 부모 컨테이너의 수직 방향 중앙에 배치
 layout_centerInParent : 부모 컨테이너의 수평과 수직 방향 중앙에 배치


 다른 위젯을 기준으로 해당 위젯을 배치하는 속성들

 layout_above : 지정한 뷰의 위쪽에 배치
 layout_below : 지정한 뷰의 아래쪽에 배치
 layout_toLeftOf : 지정한 뷰의 왼쪽에 배치
 layout_toRightOf : 지정한 뷰의 오른쪽에 배치
 layout_alignTop : 지정한 뷰의 위쪽과 맞춤
 layout_alignBottom : 지정한 뷰의 아래쪽과 맞춤
 layout_alignLeft : 지정한 뷰의 왼쪽과 맞춤
 layout_alignRight : 지정한 뷰의 오른쪽과 맞춤
 layout_alignBaseline : 지정한 뷰와 내용물의 아래쪽 기준선(baseline)을 맞춤


  android:layout_centerVertical="true"


 FrameLayout

 여러 Layout 을 중첩시켜, 원하는 Layout 만 볼 수 있도록 해준다.

 자식 View 들은 등장하는 순서대로 화면에 중첩되어 표시된다. 

 기준점은 좌측 상단이 된다.

 TableLayout

 격자모양의 배열을 이용하여 화면을 구성한다.

 자식 View 들을 테이블 형태로 배치한다.

 layout_span 은 열을 합쳐서 표시하라는 의미.

 layout_span="3" 은 현재 셀부터 3개를 합쳐서 표시하라는 의미




@ : 리소스에서 참조한다는 의미

+ : 새로 생성한다는 의미

id : 식별자를 나타내는 패키지

layout1 : 식별자


이 id 를 이용하여 activity 의 onCreate() 메소드에서 findViewById()를 호출하여 layout1 을 찾을 수 있다.

java 코드에서 참조할 일이 없으면 id를 만들지 않아도 된다.


protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main); // layout 폴더에 있는 main.xml 파일을 찾는다.

        // 화면에 나타낼 View를 지정하고, xml Layout의 내용을 메모리상에 객체화한다.

        // 이 두줄의 코드 위에 정보를 넣으면 객체화되지 않아서 강제종료 처리가 된다.

        layout1 = (LinearLayout) findViewById(R.id.layout1);  // id 가 layout1  인 것을 찾는다.


background 속성

- #RRGGBB 값을 지정한다. R:red, G:green, B:blue

- #AARRGGBB 방식인 경우 AA:투명도를 나타내며 00 : 완전투명, FF:완전불투명, 77 : 반투명


Android 폰의 해상도와 관계없이 잘 작동하는 화면을 만들 때 dp 단위를 많이 사용한다.


padding 속성

- 자신의 내부에 들어있는 위젯과 자신의 경계선과의 간격을 지정

- padding은 상하좌우 모두에 지정하는 속성

- 따로 지정하고 싶으면 paddingTop, paddingBottom, paddingLeft, paddingRight를 이용


layout_margin

- 자신의 부모 Layout 이나 위젯과의 간격, 주위의 다른 위젯과의 간격을 지정한다.



728x90

'안드로이드 > Layout' 카테고리의 다른 글

Android Fragment 기본 예제  (0) 2018.09.11
FloatingActionButton(FAB)  (0) 2018.08.15
LinearLayout weight  (0) 2018.03.01
Android ViewFlipper(뷰플리퍼)  (0) 2017.05.02
Fragment 화면 이동  (0) 2017.03.26
블로그 이미지

Link2Me

,

서버가 CentOS7 환경이라면 https://link2me.tistory.com/1842 를 참고해야 한다.


웹파일 형식으로 내보내기를 하면 속도가 짱 빠르기 때문에 사용하는데 문제가 없다.

<?php
if(!isset($_SESSION)) {
    session_start();
}

$file_name = "xxx_code.xls";
header( "Content-type: application/vnd.ms-excel; charset=utf-8");
header( "Cache-Control: must-revalidate, post-check=0,pre-check=0" );
header( "Content-Disposition: attachment; filename=$file_name" );
header( "Content-Description: PHP4 Generated Data" );


error_reporting(E_ALL ^ E_NOTICE);

include_once 'db.info.php';
include_once 'function/db.mysql.func.php';
$DB_CONNECT = isConnectDb($DB);


?>


윈도우10 환경하에서 인식이 제대로 안되는 현상이 생겨서 이번 기회에 엑셀 파일로 직접 저장하는 법을 찾아봤다.

엑셀로 저장하면 일단 속도가 많이 느리다.


https://github.com/PHPOffice/PHPExcel 에서 파일을 다운로드한다.

다운로드 한 파일을 압축을 풀어서 서버에 업로드한다.


아래 코드처럼 작성하면 된다.


<?php
if(!isset($_SESSION)) {
    session_start();
}
if(!empty($_SESSION['userID'])){
    echo "<script>window.top.location.replace('/index.php');</script>";
    exit;
}

$fname="xxx_code";  // 저장할 파일명
// 파일의 저장형식이 utf-8일 경우 한글파일 이름은 깨지므로 euc-kr로 변환해준다.
//$fname = iconv("UTF-8", "EUC-KR", "한글이름");

require_once "dbconnect.php";
require_once 'phpclass/PHPExcel.php';

$objPHPExcel = new PHPExcel();
$objPHPExcel->setActiveSheetIndex(0); //set first sheet as active

$objSheet = $objPHPExcel->getActiveSheet();
$objSheet->setTitle('코드');
$objSheet->getCell('A1')->setValue('코드');
$objSheet->getDefaultStyle('A1')->getFont()->setName('맑은 고딕');
$objSheet->mergeCells('A1:M1'); // 셀 병합
$objSheet->getStyle('A1')->getFont()->setSize(16); // 셀의 textsize

$objPHPExcel->getDefaultStyle()->getFont()->setSize(12); // 폰트 사이즈
$objSheet->SetCellValue('A2', "NO");
$objSheet->mergeCells('A2:A3'); // 셀 병합
$objSheet->SetCellValue('B2', "부서");
$objSheet->mergeCells('B2:E2');
$objSheet->SetCellValue('F2', "순서");
$objSheet->mergeCells('F2:I2');
$objSheet->SetCellValue('J2', "코드");
$objSheet->mergeCells('J2:M2');

$objSheet->SetCellValue('B3', "부서1");
$objSheet->SetCellValue('C3', "부서2");
$objSheet->SetCellValue('D3', "부서3");
$objSheet->SetCellValue('E3', "부서4");

$objSheet->SetCellValue('F3', "계위1");
$objSheet->SetCellValue('G3', "계위2");
$objSheet->SetCellValue('H3', "계위3");
$objSheet->SetCellValue('I3', "계위4");

$objSheet->SetCellValue('J3', "계위1");
$objSheet->SetCellValue('K3', "계위2");
$objSheet->SetCellValue('L3', "계위3");
$objSheet->SetCellValue('M3', "계위4");

cellColor('A2:M3', 'F28A8C'); // 헤더 배경색 지정

$i=4; // 값을 기록할 셀의 시작위치
$rowCount = 1; // 넘버링

$sql="select * from tablename where 조건";
$result=mysql_query($sql);
while($row=mysql_fetch_row($result)){


    $objSheet->SetCellValue('A'.$i, $rowCount);
    $objSheet->SetCellValue('B'.$i, $row[0]);
    $objSheet->SetCellValue('C'.$i, $row[1]);
    $objSheet->SetCellValue('D'.$i, $row[2]);
    $objSheet->SetCellValue('E'.$i, $row[3]);

    $objSheet->SetCellValue('F'.$i, $row[4]);
    $objSheet->SetCellValue('G'.$i, $row[5]);
    $objSheet->SetCellValue('H'.$i, $row[6]);
    $objSheet->SetCellValue('I'.$i, $row[7]);

    $objSheet->SetCellValue('J'.$i, $row[8]);
    $objSheet->SetCellValue('K'.$i, $row[9]);
    $objSheet->SetCellValue('L'.$i, $row[10]);
    $objSheet->SetCellValue('M'.$i, $row[11]);

    $i++;
    $rowCount++;
}

// 표 그리기
$i--;
$objSheet->getStyle('A2:M'.$i)->getBorders()->getAllBorders()->setBorderStyle(PHPExcel_Style_Border::BORDER_THIN);

// 헤더 칼럼 가운데 정렬
$objSheet->getStyle('A2:M'.$i)->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER);

// 셀 높이
$objSheet->getRowDimension(1)->setRowHeight(20);

// 칼럼 사이즈 자동 조정
$objSheet->getColumnDimension('A')->setAutoSize(true);
$objSheet->getColumnDimension('B')->setWidth(18);  // 칼럼 크기 직접 지정
$objSheet->getColumnDimension('C')->setWidth(18);
$objSheet->getColumnDimension('D')->setWidth(18);
$objSheet->getColumnDimension('E')->setWidth(18);

// 파일 PC로 다운로드
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename='.$fname.'.xlsx');
header('Cache-Control: max-age=0');

$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, "Excel2007");
$objWriter->save('php://output');
exit;

function SaveViaTempFile($objWriter){
    $filePath = '/tmp/' . rand(0, getrandmax()) . rand(0, getrandmax()) . ".tmp";
    $objWriter->save($filePath);
    readfile($filePath);
    unlink($filePath);
}

// 엑셀의 셀 배경색 지정
function cellColor($cells,$color){
    global $objSheet;

    $objSheet->getStyle($cells)->getFill()->applyFromArray(array(
        'type' => PHPExcel_Style_Fill::FILL_SOLID,
        'startcolor' => array(
             'rgb' => $color
        )
    ));
}

?>

728x90
블로그 이미지

Link2Me

,

VBA 다중정렬 코드를 찾아보니 3개까지만 키를 지원한다고 되어 있다.

그래서 일단 엑셀이 기본제공하는 다중정렬을 이용하여 정렬을 했는데 매번 찾으려니까 너무 귀찮다.

엑셀 매크로를 이용하여 코드를 기본 생성한 다음에 아래와 같이 수정했다.


E4 는 헤더열 바로 아래 셀이다.

총 4개의 열을 순서대로 정렬하기 위해 사용했다.

매크로로 만들면 실제 Sheet 명이 나오는데 전부 ActiveSheet 로 변경했다.


Sub 부서정렬()
    Dim endRow As Long
    Dim CurrentPostion

    endRow = Cells(Rows.Count, "A").End(3).Row  '// 셀을 추가하면 마지막 행의 위치가 계속 변함

   

    CurrentPostion = ActiveCell.Address    '// 현재 커서가 있는 셀을 변수에 담는다.
   
    ActiveSheet.AutoFilter.Sort.SortFields.Clear
    ActiveSheet.AutoFilter.Sort.SortFields.Add Key:= _
        Range("E4:E" & endRow), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
    ActiveSheet.AutoFilter.Sort.SortFields.Add Key:= _
        Range("F4:F" & endRow), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
    ActiveSheet.AutoFilter.Sort.SortFields.Add Key:= _
        Range("G4:G" & endRow), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
    ActiveSheet.AutoFilter.Sort.SortFields.Add Key:= _
        Range("H4:H" & endRow), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
    With ActiveSheet.AutoFilter.Sort
        .Header = xlYes
        .MatchCase = False
        .Orientation = xlTopToBottom
        .SortMethod = xlPinYin
        .Apply
    End With
   
    Range(CurrentPostion).Select
End Sub

728x90
블로그 이미지

Link2Me

,

VBA 서식을 복사해서 한번에 처리해야 할 경우의 코드이다.


Sub Replace()
    Dim C As Range
    Dim rng As Range
   
    Set rng = Selection
   
    For Each C In rng
        C.Replace " ", "", xlPart
        If InStr(C, "팀") = 0 Then
            C = C & "팀"
        End If
       
        rng.Offset(-1, 0).Copy
        rng.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
        Application.CutCopyMode = False

    Next C 
   
End Sub

728x90
블로그 이미지

Link2Me

,

리눅스를 호스팅업체에서 최신버전으로 설치를 해준 것이 있는 상태에서 다른 걸 테스트해야 할 경우가 있었다.

즉, 최신버전의 APM 에서는 동작이 되지 않았다.


고민하다가 호스팅업체에 문의를 해보니 이미 설치된 리눅스 버전의 이름을 변경하고 나서 다시 소스 컴파일을 해보면 된다고 했다.


그래서 소스 컴파일을 다시 해봤더니 잘 되었다.


변경해서 사용할 일(테스트)이 생기면 디렉토리 이름만 서로 변경하여 사용한다.

물론 변경하고 나면 DB 인식등은 새로 해주어야 한다.


1. 디렉토리 이름 변경전에 할일

   모든 웹서버 데몬 죽이기 : killall httpd

   MySQL 데몬 중지 :  /etc/init.d/mysqld stop


2. 새로운 APM 설치

    APM 이 설치되어 있지 않은 상태에서는

    먼저 기존 apache, php, mysql 디렉토리 이름에 날짜 또는 다른 식별자로 표시하여 디렉토리명을 변경한다.

    그 다음에 APM(Apache + PHP + MySQL)을 소스 컴파일한다.

    그러면 apache, php, mysql 디렉토리가 새로 생긴다.


3. 디렉토리 이름 서로 변경


4. 데몬 구동

    MySQL Start : /etc/init.d/mysqld start

    HTTPD Start : /etc/init.d/httpd start


5. MySQL root 비밀번호가 생각나지 않아서 접속해서 작업을 못하는 상황이 생겼다.

   이럴 경우에는

ps -ef | grep mysql
killall mysqld
cd /usr/local/mysql/bin/
./mysqld_safe --skip-grant &
# 대기모드 상태가 된다. 여기서 엔터키를 치면 대기모드에서 빠져나오므로
# 아래 작업이 끝나기 전에는 엔터키를 치지 말아야 한다.

# 또다른 콘솔창을 하나 더 띄운 상태에서 실행
mysql -u root -p
mysql> use mysql;
mysql> UPDATE user SET password=password('ROOT_비밀번호') WHERE user='root';
mysql> flush privileges;
mysql> quit

#### mysql 데몬 다시 구동
/etc/init.d/mysqld start



6. 새로운 DB 세팅 및 사용자 권한 부여 방법

    색상 표시를 한 부분은 원하는 형태로 변경하여 사용할 부분임

   // DB 생성
      create database webdb default character set utf8;

   // 새로운 Database 를 생성하고 사용자에게 권한을 부여하는 방법
      mysql > use mysql;
      mysql > create user web@localhost identified by 'passwdsetting';
   // 사용자(user)를 추가하면서 패스워드까지 설정
      mysql > grant all privileges on webdb.* to web@localhost;
      mysql > flush privileges;

   // 권한 회수
      revoke all on webdb.* from web@localhost;

   // 권한확인
   show grants for web@localhost;


728x90
블로그 이미지

Link2Me

,

시스템에서 엑셀로 받은 자료를 가지고 작업을 하다보니 한줄로 표시되어야 하는데 두줄로 표시가 되는 것이 있다.

에러의 원인이 되어 원하는 결과가 나오지 않는다.


그래서 VBA 코드를 만들어서 해결했다.


Sub 셀내줄바꿈해제()
    Dim rngC As Range
    Dim rngAll As Range
    Dim endRow As Long
  
    Application.ScreenUpdating = False
    endRow = Cells(Rows.Count, "A").End(3).Row
    If endRow < 4 Then
        endRow = 4
    End If
   
    Set rngAll = Range([H4], Cells(endRow, "H"))
  
    For Each rngC In rngAll
        If InStr(rngC, Chr(10)) Then
            rngC.Interior.ColorIndex = 6
            rngC = Replace(rngC, Chr(10), "")
        End If
    Next rngC
  
    MsgBox "완료"
End Sub


728x90
블로그 이미지

Link2Me

,

PHP 를 이용하여 MySQL 칼럼명을 가져오는 코드를 필요했다.

테이블을 INNER JOIN 하면서 select * from tableA a, tableB b where a.uid=b.uid 로 하면 tableA 와 tableB의 모든 칼럼을 가져오게 된다.


가져오고 싶은 것은 tableA의 칼럼만 가져오고 싶어서 함수로 구현했다.


<?php
require_once $_SERVER['DOCUMENT_ROOT'].'/dbconnect.php'; //db접속

echo getColumns('member_table'); // table name

function getColumns($table){

    global $DB_CONNECT;
    $fields = array();
    $res=mysql_query("SHOW COLUMNS FROM ".$table."");
    while ($x = mysql_fetch_assoc($res)){
      array_push($fields,$x['Field']);
    }

    for($i = 0; $i < count($fields); $i++){
        $columns = join($fields,",");
    }
    return $columns;
}

?>


728x90
블로그 이미지

Link2Me

,

<!DOCTYPE html>
<head>
<meta charset=UTF-8" />
<meta name="robots" content="noindex,nofollow"/> <!-- 검색엔진에서 검색 제외 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"/>
<meta http-equiv="X-UA Compatible" control="IE=edge,chrome=1" /> <!--브라우저 호환성 설정 -->
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
$(function(){
    $("#sel2").click(function(){
        cw=screen.availWidth;     //화면 넓이
        ch=screen.availHeight;    //화면 높이

        sw=cw/2;    //띄울 창의 넓이
        sh=ch/2;    //띄울 창의 높이

        ml=(cw-sw)/2; //가운데 띄우기위한 창의 x위치
        mt=(ch-sh)/2; //가운데 띄우기위한 창의 y위치

        var url = $("#sel").val();
        if(url != '0'){
            window.open(url, 'tst','width='+sw+',height='+sh+',top='+mt+',left='+ml+',resizable=no,scrollbars=yes');
        }

    });
});
</script>
<body>
<select id="sel">
  <option value="0" >선택 사이트로 이동</option>
  <option value="http://link2me.tistory.com">My Blog</option>
  <option value="http://www.naver.com">네이버</option>
  <option value="http://www.daum.net">다음</option>
 </select><a href="#" id="sel2" >이동</a>

</body>
</html>

728x90
블로그 이미지

Link2Me

,

안드로이드 앱 프로그래밍 책과 인터넷 검색을 통해서 안드로이드 앱 프로그램을 만드는 연습을 하다보니 한계에 부딪치기 시작했다.

인터넷에 올라온 소스코드를 가지고 테스트를 해보니 전화번호부 가져오기를 하다보니 원하지 않게 값이 저장된다. 거의 유사한 코드들이 복사해서 돌아다니고 있다.

그래서 자바 책을 들여다보면서 기본적인 사항을 내 나름대로 조금씩 정리를 해둔다.

처음부터 문법만 접하면 어떻게 활용해야 하는지를 몰라서 성취감이 없다.

목표를 정하고 만들어야겠다는 걸 하기 위해 기능을 하나씩 익히고 부족하면 문법사항을 들여다보면서 배우는게 초보자인 나에게는 효율적이다.

부족하지만 그동안 작성해두었던 게시물 중심으로 샘플을 활용하여 작성해둔다.


주석문

// 한줄 주석


/*

여러줄 주석

*/ 


/**

 document 생성용 주석

*/



변수(Variable) : 프로그램이 실행되는 동안 데이터를 저장하기 위한 공간

- 메모리 공간 할당 + 메모리 공간의 이름

- int 와 같이 변수의 특성을 결정짓는 키워드를 가리켜 자료형이라 한다.

- 변수 이름의 제약 사항

  . 숫자로 시작 불가

  . $와_ 이외의 다른 특수문자는 사용불가

  . 키워드는 변수의 이름으로 사용 불가

- short 형 데이터는 int형 데이터로 자동 변환한다.

- 자바에서는 true 와 false는 그 자체로 저장이 가능한 데이터이다.

- 1과 '1'은 서로 다르다.

지역변수

 - Local Variable(지역변수)는 메서드 안에 선언된 변수를 말한다.

 - 사용자가 직접 초기화를 해주어야 한다. 초기화를 안하면 에러가 발생한다.

 - 지역변수 생성 시점은 해당 메서드가 수행될 때이다.

 - 메서드 수행이 끝나면 지역변수는 메모리에서 사라진다.

 멤버변수

 - Member Variable(멤버변수)는 클래스 안에 선언된 변수를 말한다.

 - 사용자가 초기화를 하지 않아도 시스템에 의해서 자동으로 초기화된다.

   하지만 프로그램의 정확성을 위해 직접 초기화하는 습관이 필요하다.

 - 멤버변수는 static 으로 선언된 변수와 인스턴스 변수가 있다.

 - static 변수는 객체를 생성하지 않고, 클래스 이름으로 참조할 수 있다.

 - 인스턴스 변수는 반드시 객체를 생성한 후 객체 레퍼런스를 통해서 참조해야 한다.



안드로이드앱 프로그래밍 동영상 강좌를 듣다보면 casting 이란 말이 엄청 나온다.

casting(형변환)은 변수 또는 리터럴의 타입을 다른 타입으로 변환하는 것을 말한다.

int score = (int) 88.3; // double 형의 값을 int 형으로 변환하여 88을 저장한다.


배열은 PHP 에서도 정말 많이 활용된다. C#에서도 배열의 필요성을 많이 알게되었다.

소스코드를 접하면서 내가 소홀하게 무심코 넘겼던 것을 알게되었고, 배열의 사용이 정말 중요하고 많더라.


배열(array)을 선언한 다음에는 배열을 생성해야 한다.

- 배열 선언 : 참조변수를 위한 공간 만들기

  int [] grades;

- 배열 생성 : new 키워드를 이용하여 배열을 생성한다. 데이터를 저장할 수 있는 공간이 만들어진다.

  grades = new int[5];

- 배열은 같은 타입의 데이터만 여러개 생성한다.

- 배열의 길이는 length 속성을 이용하면 알 수 있다.

- 배열의 크기를 키보드 입력 값을 받아서 지정할 수 있다.

  int n = 10;

  int [] grades = new int[n];

- 배열에서 최대값, 최소값을 구할 때 int max = 0; 이라는 초기값을 지정하는 것은 오류가 발생할 수 있다.

  최대값이 음수일 수도 있는데, 초기값을 0 으로 선언하면, 0보다 작으므로 원하지 않는 결과가 나온다.


배열의 복사

배열에서 조건에 맞는 데이터만 복사하고 싶은 경우가 있다.

이때 for 문으로 돌리면서 if 조건문으로 해당되는 데이터만 복사하면 된다.


배열의 단점

ㅇ 크기를 변경할 수 없다.

    - 크기를 변경할 수 없으므로 새로운 배열을 생성해서 데이터를 복사하는 작업이 필요하다.

    - 실행속도를 향상시키기 위해서는 충분히 큰 크기의 배열을 생성해야 하므로 메모리가 낭비된다.

ㅇ 비순차적 데이터의 추가 또는 삭제에 시간이 많이 걸린다.

    - 차례대로 데이터를 추가하고 마지막에서부터 데이터를 삭제하는 것은 빠르지만,

    - 배열의 중간에 데이터를 추가하려면, 빈자리를 만들기 위해 다른 데이터들을 복사해서 이동해야 한다.


equals()는 두 배열에 저장된 모든 요소를 비교해서 같으면 true, 다르면 false를 반환한다.

equals()는 일차원 배열에서만 사용 가능하다.

다차원 배열 비교는 deepEquals()를 사용해야 한다.



메서드 : 코드 블럭에 이름을 붙여 놓은 것을 말한다.

- return type : 메서드는 블록 안의 코드를 실행한 다음 결과를 반환할 수 있다.

- return 값이 필요없는 경우는 void 라고 적는다.

- 반환한 값이 있다면 데이터의 유형에 따라 byte, short, int, long, float, double, char, boolean, 배열, 클래스 이름을 적는다.

- 매개변수 : 외부로부터 값을 전달받는데 사용된다.

- 메서드를 작성하는 가장 큰 이유는 반복적으로 사용하는 코드를 줄이기 위함이다.

- 하나의 메서드는 한가지 기능만 수행하도록 작성하는 것이 좋다.


Java에서 매개변수 전달방식은 call-by-value 이다.
Java 에서 문자열 비교는 compareTo
if(names[j].compareTo(names[j+1]) > 0){ }


method overloading : 한 클래스 내에 같은 이름의 메서드(함수)를 여러개 정의하는 것을 말한다.

- 메서드 이름이 같아야 한다.

- 매개변수의 개수 또는 타입이 달라야 한다.

- 매개변수는 같고 리턴타입이 다른 경우는 오버로딩이 성립되지 않는다.


public class Contacts {
    public void ContactsIDInsert(ContentResolver cr, Context context, String strName, String strMobileNO) {
        //코드 작성
    }

    public void ContactsIDInsert(ContentResolver cr, Context context, String strName, String strMobileNO, String strOfficeNO) {
        //코드 작성
    }

    public void ContactsIDInsert(ContentResolver cr, Context context, String strName, String strMobileNO, String strOfficeNO, String strEmail, String strPhoto) {
        //코드 작성
    }

}


오버라이딩(overriding)

조상 클래스로부터 상속받은 메서드의 내용을 변경하는 것을 오버라이딩이라고 한다.

overriding 의 조건

- 이름이 같아야 한다.

- 매개변수가 같아야 한다.

- 리턴타입이 같아야 한다.

- static, final, private 가 지정된 메소드는 오바라이딩 불가


try catch finally 문

try {

   예외 발생 가능성이 있는 문장들;

}
catch (예외타입 메개변수명){

   예외타입의 예외가 발생할 경우 처리 문장;

}
finally {

   항상 수행할 필요가 있는 문장들;

   // 필수 블록은 아니다

}

그냥 무조건 항상 실행되는 것이 아니라 finally 와 연결되어있는 try 블록으로 일단 진입을 하면,
무조건 실행되는 영역이 바로 finally 블록이다.
중간에 return 문을 실행하더라도 finally 블록이 실행된 다음에 메소드를 빠져나간다.


728x90

'안드로이드 > Java 문법' 카테고리의 다른 글

[Java] 정보은닉과 캡슐화  (0) 2017.10.16
자바 기본 데이터형과 크기  (0) 2017.10.11
Java 클래스(Class) ★★★★★  (0) 2017.05.04
ArrayList and HashMap  (0) 2017.03.06
Java foreach 문  (0) 2017.03.01
블로그 이미지

Link2Me

,

<input type="button" id="orderBtn" name="Test" value = "순서변경"></button>


MouseOver 시 손가락 모양 표시

css로 손가락 모양을 만든다.


    $('#orderBtn').css("cursor","pointer").click(function() {
        $.ajax ({
            type:"POST",
            url:"./order_process.php",
            data:ordered_items,
            success:function(data) {
                alert ("서열순서를 DB에 반영했습니다.");
            }
        });   
    });

728x90

'Web 프로그램 > js, jQuery' 카테고리의 다른 글

jQuery 모달(dialog) 코드 이해하기  (2) 2016.10.11
jQuey 새창 띄우기  (0) 2016.07.11
jQuery 모달(modal) 윈도우  (0) 2016.05.01
JSON 기초  (0) 2016.04.24
부모창 새로 고침  (1) 2016.04.10
블로그 이미지

Link2Me

,

테이블 게시글 순서를 변경 저장해야 할 경우가 있다.

그래서 jQuery tableDnD 를 이용해서 테스트한 것을 적어둔다.


마우스로 Drag 하여 놓기를 하고  순서변경만 누르면 DB에 반영된다.




파일은 https://github.com/isocra/TableDnD 에서 다운로드 받아 jquery.tablednd.js 만 include 한다.


순서를 변경하는 것은 직급 서열 순서를 변경하는 경우에 처리할 것이므로, 화면에 표시할 게시글수를 2페이지로 분리해서 나오도록 하면 안된다.

그래서 limit 에 조건을 만족하는 개수만큼 표시되도록 처리했다.


<?php
session_start();
// 세션 검사 처리는 생략
// DB 연결
include_once $_SERVER['DOCUMENT_ROOT'].'/db.info.php';
require_once $_SERVER['DOCUMENT_ROOT'].'/phpclass/dbClass.php';
$c=new MySQLDbClass();
$DB_CONNECT = $c->isConnectDb($DB);

$where =""; // where 조건문
$limit = $NUM = $c->getDbRows('BOOKS',''); // 조건에 맞는 게시글 개수
$flddata ="uid, title, price, category, orderNO";
$orderby = "orderNO";
$curPage = 1;
$result = $c->getDbArray('BOOKS',$where,$flddata,$orderby,$limit,$curPage);

?>

<!DOCTYPE html>
<head>
<meta charset=UTF-8" />
<meta name="robots" content="noindex,nofollow"/> <!-- 검색엔진에서 검색 제외 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"/>
<meta http-equiv="X-UA Compatible" control="IE=edge,chrome=1" /> <!--브라우저 호환성 설정 -->
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="js/jquery.tablednd.js"></script>
<style>
body {font-family: "맑은 고딕";}
table,td,th {border: 1px solid #000;border-collapse:collapse;padding:5px;}
/*사용자 정의 스타일 */
.dragRow {background-color: #fee;}

td.dragHandle {}

td.showDragHandle {
    background-image: url(images/updown2.gif);
    background-repeat: no-repeat;
    background-position: center left;
    cursor: move;
}

table td {padding:5px;}
</style>

<script>
$(function() {
    var ordered_items;
    $('#table_1').tableDnD({
        onDragClass: "dragRow",
        onDrop: function(table, row) {
        ordered_items = $.tableDnD.serialize('id');
        }
    });

    $('#btn_order').css("cursor","pointer").click(function() {
        $.ajax ({
            type:"POST",
            url:"./order_process.php",
            data:ordered_items,
            success:function(data) {
                alert ("서열순서를 DB에 반영했습니다.");
            }
        });   
    });


    // class td1 중에서 짝수번째 요소만 선택해서 배경색을 지정색으로 표시
    $(".tr1:odd").css("background-color","#F4F9FF");

}); // ready

</script>
<body>
<div class="container">
    <div id="article">
        총 : <?php echo number_format($NUM)?> 개
    </div>

    <section id="content">
        <table id="table_1" border="1" style="width:800px;">
        <tr class="nodrop nodrag"><!-- Drag & Drop 제외 -->
            <th>uid</th>
            <th>타이틀</th>
            <th>가격</th>
            <th>구분</th>
            <th style="width:50px;">순번</th>
        </tr>
        <?php
        while($row = mysql_fetch_array($result)){
            echo '<tr id="'.$row[0].'" class="tr1">';
            for($i=0;$i < count(explode(",",$flddata)); $i++){
                echo '<td>'.$row[$i].'</td>';
            }
            echo '</tr>';
        }
        ?>
        </table>
        <input type="button" id="btn_order" name="Test" value = "순서변경"></button>
    </section><!-- content -->
</div><!-- container -->
</body>
</html>


===== order_process.php =====

<?php
if(!isset($_POST['table_1'])) {
    echo 'error';
    exit;
}

$table_1 = $_POST['table_1'];
foreach ($table_1 as $key=>$value) {
    // 정렬순서 변경내역 DB에 반영
    require_once $_SERVER['DOCUMENT_ROOT'].'/dbconnect.php'; // db접속
    $query = 'UPDATE BOOKS SET orderNO = '.($key+1).' WHERE uid = '.$value.' LIMIT 1';
    mysql_query($query) or die (mysql_error());
}

?>



728x90
블로그 이미지

Link2Me

,

테이블 게시물 순서 바꾸기를 연습해봤다.

테이블 순서를 변경해주는 jQuery 소스는 https://github.com/isocra/TableDnD 에서 받을 수 있다.

jquery.tablednd.js


첨부로 올린 이 파일을 받아도 된다.

이것은 테이블에서 마우스로 위아래 게시물 순서를 변경할 수 있다는 것만 연습해볼 수 있다.

DB와 연동하여 실제 게시물 순서를 변경하는 것 까지는 안된다.

하지만 거의 DB에서 가져온 것과 같은 결과를 얻어내는 방법까지 설명을 추가했다.


<!DOCTYPE html>
<head>
<meta charset=UTF-8" />
<meta name="robots" content="noindex,nofollow"/> <!-- 검색엔진에서 검색 제외 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"/>
<meta http-equiv="X-UA Compatible" control="IE=edge,chrome=1" /> <!--브라우저 호환성 설정 -->
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="js/jquery.tablednd.js"></script>
<style>
body {font-family: "맑은 고딕";}
table,td,th {border: 1px solid #000;border-collapse:collapse;padding:5px;}
/*사용자 정의 스타일 */
.dragRow {background-color: #eee;}

td.dragHandle {}

td.showDragHandle {background-image: url(images/updown2.gif);
    background-repeat: no-repeat;background-position: center left;
    cursor: move;
}

table td {padding:5px;}
</style>

<script>
$(function() {
    var ordered_items;
    onDragClass: "drag",
    $('#table_1').tableDnD({
        onDrop: function(table, row) {
        ordered_items = $.tableDnD.serialize('id');
        }
    });

    $('#btn_order').click(function() {
        $('#result').load("test.php?" + ordered_items);
    });

});
</script>
</script>


<div id="result">테이블 순서변경 결과 메시지 보여주는 곳</div>
<br>
<table id="table_1" border="1" style="width: 500px;">
    <tr id="1"><td>1</td><td>첫번째</td></tr>
    <tr id="2"><td>2</td><td>두번째</td></tr>
    <tr id="3"><td>3</td><td>세번째</td></tr>
    <tr id="4"><td>4</td><td>네번째</td></tr>
    <tr id="5"><td>5</td><td>다섯번째</td></tr>
</table>
<input type="button" id="btn_order" name="Test" value = "순서변경"></button>


</body>
</html>


===== test.php =====

<?php
$table_1 = $_GET['table_1'];
echo '저장순서 : ';
foreach ($table_1 as $key=>$value) {
    echo '순번 '. ($key+1) . ' 번의 DB idx = '. $value . ', ';
    // DB에 결과를 반영하고자 하는 쿼리문을 적어준다
    // $query = 'UPDATE table SET orderNO = '.($key+1).' WHERE idx = '.$value.' LIMIT 1';
    // mysql_query($query) or die (mysql_error());
}

?>


DB에서 읽어온 파일을 테이블로 구성한다면 <tr id='row['idx']'> 에 값이 저장되도록 한다.

테이블의 순서를 변경하면 자동으로 DB에 저장된 순서로 orderNO 에 순서의 값이 저장된다.


게시물을 읽어서 테이블에 보여주는 개수를 잘 처리하는 것이 중요 포인트가 될 수도 있다.

가령 뽑아내야 할 게시글의 수가 18개 였다고 가정해보자.

그러면 화면에서는 18개가 모두 나오도록 처리하는게 중요하다.

화면에 출력해야 할 Query 문의 개수(count)를 구한 다음에 그 개수만큼 출력하려면 LIMIT $count 만큼 나오도록 쿼리문을 만들어야 한다.

728x90
블로그 이미지

Link2Me

,

UI 디자인을 하고 자바코딩을 하고 나서 어플이 제대로 동작하는지 확인하는 과정이다.

Eclipse 를 처음 실행해 볼 때에는 이렇게 한다는 것도 몰랐었다.

초보자에겐 역시 어려운 과정인 셈이다.


1. 스마트폰을 USB 케이블로 컴퓨터에 연결한다.


2. Eclipse 에서 아래 그림과 같이 실행한다.

    폰에 앱을 설치하여 잘 동작하는지 확인해보고자 하는 과정으로

    해당 파일에서 마우스 우클릭을 하여 실행한다.



이제 휴대폰을 선택하고 OK를 누르면 내 스마트폰으로 테스트 어플을 구동시켜 볼 수 있다.

안드로이드 스마트폰으로 디버깅하는 방법이 가장 빠르게 원하는 결과를 알 수 있다.

에뮬레이터로 실행하면 시간이 많이 걸린다.



728x90
블로그 이미지

Link2Me

,

SQL 인젝션 공격을 방지하기 위한 로그인 함수 사용예이다.

공격코드로 사용하는 특수문자를 전부 공백으로 대체시켜 버리도록 했다.


function UserAuthCheck($userID,$passwd) {
    if(!isset($userID) || !isset($passwd) || empty($userID) || empty($passwd)) {
        return 0;
    } else {
        global $DB_CONNECT;           
        $userID = preg_replace("/[\s\t\'\;\"\=\-\-]+/","", $userID); // 공백이나 탭 제거(사용자 실수 방지)
        $passwd = preg_replace("/[\s\t\'\;\"\=\-\-]+/","", $passwd); // 공백이나 탭 제거, 특수문자 제거(",',;,=,--)
        // SQL injection 검사
        $userID = htmlentities($userID); // <script>documnet.cookie();</script> 공격 방지, 한글인식 불가
        $passwd = htmlentities($passwd); // < 를 \< 로 바꿔준다.
        //$userID = str_replace(array("'",""","'",'"'), array("&#39;","&quot;","&#39;","&quot;"), $userID);
        if(preg_match('/(and|null|where|limit)/i', $userID)) { $this->popup('비정상적 접근입니다');} // i는 대소문자 구별하지 말라
        if(!preg_match('/^[0-9a-zA-Z\~\!\@\#\$\%\^\&\*\(\)]{7,}$/',$passwd)) { // 최소7자리 이상 허용 문자만 통과
            $this->popup('정보가 올바르지 않습니다');
        }

        $sql = "select code, id ";
        $sql.= "from memberdata where pw=md5('".$passwd."') and id= '".$userID."' ";
        if($result = mysqli_query($DB_CONNECT,$sql)) { //성공
            $row = mysqli_fetch_array($result);
            if($row == NULL) $this->popup('정보가 올바르지 않습니다');
                return $row;
            } else {
                $this->popup('정보가 올바르지 않습니다');
        }
    }
}

728x90
블로그 이미지

Link2Me

,