반응형

    Function ARRAYMERGE( arr1, arr2 )

        dim arr1_size, arr2_size, total_size, i, counter

        

        if not isArray( arr1 ) then 

            arr1 = Array( arr1 )

        end if

        

        if not isArray( arr2 ) then 

            arr2 = Array( arr2 )

        end if

        

        arr1_size = ubound( arr1 ) : arr2_size = ubound( arr2 )

        total_size = arr1_size + arr2_size + 1

        counter = arr1_size + 1

        

        Redim Preserve arr1( total_size )

        For i = lbound( arr2 ) to arr2_size

            If isobject( arr2( i ) )then

                set arr1( counter ) = arr2( i )

            Else

                arr1( counter ) = arr2( i )

            End if

            counter = counter + 1

        Next

        ARRAYMERGE = arr1

    End Function

반응형
Posted by Hippalus
,

반응형

DIV태그 안에 컨텐츠를 넣고 프린트시 자칫 짤림 현상이 나타날 수 있음
이때 style로 media print에 클래스로 아래와 같이 지정해주고 div에 해당 클래스명을 지정해주면 프린트 할 때 알아서 다음 페이지로 잘 넘어가진다.

<style type="text/css">
        @media print {
            .page-break { page-break-inside:avoid; page-break-after:auto }
        }
</style>

<div class="page-break">
    <div><br>TEST</div>
</div>
<div class="page-break">
    <div><br>TEST</div>
</div>
.
.
.
<div class="page-break">
    <div><br>TEST</div>
</div>

$("#BTNE").click(function(e) {
    e.preventDefault();

   
window.print();
});

 

반응형
Posted by Hippalus
,

반응형

보통 Xcode에서 빌드시 연결 오류가 나면 연결잭을 분리 후 다시 연결하면 대부분 해결 되는데 이번엔 해결 되지 않고 이런 오류를 내뱉는다.

이럴 땐 아이폰을 재시작하면

해결된다.


잘 동작한다.

항상 느끼지만 윈도우 개발보다 모바일 앱 개발은 디바이스부터 개발 언어의 잦은 변경질까지 다양한 요소들까지 신경써줘야 한다.

반응형
Posted by Hippalus
,

반응형

iOS 앱을 만들다 보면 가장 처음 접하게 되는 문제가 이 키보드 가림 문제이다.
보통 책이나 웹상에 떠도는 소스들을 보다보면 매우 간단하게 UITextFiled 하나만 배치하여 키보드가 나타나면 뷰를 올려주고 키보드가 내려가면 다시 뷰를 내려주는 단순한 상황만 언급할 뿐 실제 현업에서 발생 가능한 UITextField가 여러개일 때
즉 상단에 위치한 UITextField컨트롤은 키보드가 보여줘도 그대로 놔둬야 하고 하단에 위치한 UITextField 컨트롤은 키보드만큼 올려줘야 하는 상황에 대해 제대로 해결책을 제시하는 글은 찾기 힘들다.
오늘 소개할 이 방법 말고도 여러 방법들이 있겠지만 초보자도 쉽게 따라할 수 있는 방법을 택하여 소개하고자 한다.

대략 순서는 이러하다.
1. viewDidLoad에서 UITextField Delegate  연결 
2. viewDidLoad에서 NotificationCenter를 이용하여 Observer 등록 : 키보드 Show, Hide 이벤트 확인
3. UITextField가 키보드에 가려졌는지 확인을 위한 해당 컨트롤의 위치좌표(Y) 확인
4. 가려졌다면 뷰 이동 O, 안가려졌다면 뷰 이동 X
5. 모든 작업 종료 후 viewWillDisappear에서 2번에서 등록했던 Observer 제거

입력 전 화면
첫번째 컨트롤에 포커스 된 화면(키보드가 가려지지 않으므로 뷰 이동 X)
두번째 컨트롤에 포커스 된 화면(키보드가 가려졌으므로 뷰 이동 O)
세번째 컨트롤에 포커스 된 화면(키보드가 내려간 상태였다면 뷰 이동이 되어야 하지만 이미 키보드가 올라온 상태이므로 뷰 이동 X)

1. TextField의 처리를 위해 UITextFieldDelegate 프로토콜 추가
(이후 TextField 컨트롤은 편의상 컨트롤이라 칭함)
class
MyViewController: UIViewController, UITextFieldDelegate {
}

2. 컨트롤 변수와 컨트롤을 연결(너무 기초라 패스)
위에서부터 순서대로 txtTmp, txtId, txtPw
    @IBOutlet weak var txtTmp: UITextField!
    @IBOutlet weak var txtId: UITextField!
    @IBOutlet weak var txtPw: UITextField!

3. viewDidLoad()에서 컨트롤 변수의 delegate 연결 및 키보드를 내리기 위해 완료 버튼(done)을 추가해준다.
        txtTmp.delegate = self
        txtId.delegate = self
        txtPw.delegate = self

        txtTmp.returnKeyType = .done
        txtId.returnKeyType = .done
        txtPw.returnKeyType = .done

4. 키보드가 올라왔나 내려갔나 확인을 위해 NotificationCenter로 Observer 등록        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
이렇게 구현하면 keyboardWillShow, Hide가 없다고 에러가 뜰텐데 원칙상 선 구현 후 정의를 내려야 하지만 편의상 그냥 구현한다.

5. 키보드가 올라왔을 때 컨트롤이 키보드에 가려졌을 때 뷰를 그만큼 올려주는 처리와 내려갔을 때 뷰의 위치를 다시 되돌려 놓는 처리 그리고 지금 컨트롤이 키보드에 가려졌는지 안가려졌는지 확인을 위한 처리 구현

먼저 키보드가 컨트롤을 가렸는지 확인을 위해 변수 하나를 실수형으로 선언한다.
    var
fCurTextfieldBottom: CGFloat = 0.0

현재 포커싱된 컨트롤의 좌표를 구하기 위해 textFieldDidBeginEditing에서 현재 컨트롤의 y좌표와 해당 컨트롤의 높이를 더하면 나중에 키보드에 의해 가려졌는지 확인이 가능하므로 계산 후 일단 보관해둔다.
    func textFieldDidBeginEditing(_ textField: UITextField) {        
        fCurTextfieldBottom = textField.frame.origin.y + textField.frame.height    
    }

이제 4번에서 등록한 selector함수인 키보드가 나타났을 때와 내려갔을 때 함수를 구현한다.
키보드의 사이즈(구조체)를 keyboardSize에 보관 후 현재뷰의 높이에서 빼주면 키보드가 잡아먹는 정확한 위치를 알 수 있다.
이를 앞서 계산해 보관해둔 fCurTextfieldBottom와 비교하여 fCurTextfieldBottom가 작거나 같으면 가려지지 않았으니 무시하고 크다면 1px이라도 가려졌으므로 현재 뷰를 키보드가 잡아먹는 높이만큼 올려주면 된다.
    @objc func keyboardWillShow(notification: NSNotification) {
        if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
            if fCurTextfieldBottom <= self.view.frame.height - keyboardSize.height {
                return
            }
            if self.view.frame.origin.y == 0 {
                self.view.frame.origin.y -= keyboardSize.height
            }
        }
    }

키보드가 사라졌을 땐 간단하다.
그냥 뷰가 이동됐으면 다시 원상복구해주고 아니면 아무런 처리를 하지 않는다.
    @objc func keyboardWillHide(notification: NSNotification) {
        if self.view.frame.origin.y != 0 {
            self.view.frame.origin.y = 0
        }
    }

앞서 추가했던 done의 처리도 해주어 키보드가 내려가게끔 구현해준다.
    func textFieldShouldReturn(_ textField: UITextField) -> Bool
         textField.resignFirstResponder()
         return true
     }

이렇게만 해두면 기본적인 처리는 다 되었고 만약 완료버튼(done) 대신 뷰의 아무곳이나 터치했을 때 키보드가 내려가길 원한다면
viewDidLoad에 제스쳐를 등록 후 
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(endEditing)))

관련 함수를 구현해주면 깔끔하게 처리가 가능하겠다.
   
@objc func endEditing() {
        txtTmp.resignFirstResponder()
        txtId.resignFirstResponder()
        txtPw.resignFirstResponder()
    }

 

반응형
Posted by Hippalus
,

반응형

- (void)viewDidLoad {
     [super viewDidLoad];

     
UIView *view = [UIView new];
     view.backgroundColor = [UIColor redColor];

     
[view setTranslatesAutoresizingMaskIntoConstraints:NO];
     [self.view addSubview:view];
     
     NSLayoutConstraint *left = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeLeftrelatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1 constant:100];

     NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1 constant:100];

     NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:50];

     NSLayoutConstraint *width = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:50];

     [self.view addConstraints:@[left, top]];
     [view addConstraints:@[height, width]];
}


width에 constant를 뷰의 넓이와 동일하게 한다면
CGRect rcData = [[UIScreen mainScreen] bounds];
     NSLayoutConstraint *width = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:rcData.size.width];


반응형
Posted by Hippalus
,

반응형

vue.js를 설치하기 위해선 npm을 통해 설치하여야 하지만 npm을 이용하기 위해선 또 brew를 선설치하여야 한다.
brew.sh/index_ko로 이동해보면 아래와 같이 친절하게 터미널 명령어가 존재하는데 이를 복사하여 터미널에 붙여넣기 후 엔터를 친다.

Homebrew 홈페이지

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

그럼 sudo 권한을 위해 아이맥 비밀번호를 물어보고 이를 입력하면 한참을 다운로드에서 머물다 설치가 마무리 된다.
대략 20분 이상 걸린것 같다.(회사라 느린것인지 모름)

Terminal Homebrew 설치화면

Homebrew가 설치 되었다면 이제 node를 설치한다.
터미널에서 brew install node 를 입력하고 엔터

node 설치화면

npm이 설치되었으니 이제 본격적인 vue cli 설치를 진행한다.
터미널에서 npm install -g @vue/cli 를 입력하고 엔터
(CLI란 뷰 프로젝트를 빠르게 개발하고 빌드하고 서비스를 런칭시켜주는 틀)

다른 설치파일들과 달리 1~2분 이내로 금방 설치가 완료 된다.

vue 설치 완료 화면

기본 설치까지 모두 완료 되었으므로 이제 실제 vue 프로젝트를 생성해보도록 한다.
프로젝트 생성방법은 터미널에서 vue create 폴더명이므로
vue create test 입력 후 엔터

참고로 화살표키로 다른 기본 설치와 매뉴얼 설치를 선택할 수 있다.

기본 옵션설치이므로 default에서 엔터 설치

default 그대로 설치 진행 중 화면


프로젝트 설치가 완료되면 아래와 같이 생성된 프로젝트를 실행해 볼 수 있도록 친절히 안내가 나온다.
(node.js를 경험해봤다면 익숙한 방식이다.)

🎉  Successfully created project test.
👉  Get started with the following commands:
 $ cd test
 $ npm run serve

실제 ls 명령어를 통해 폴더를 확인해보면 test란 폴더가 생성되어 있고

우측 끝에 test란 폴더가 보임

cd 명령어를 통해 이동해보면 아래와 같은 구조로 프로젝트가 생성되어 있음을 알 수 있다.
test
    src
        App.vue
        assets
        components
        main.js

생성된 프로젝트를 실행하고 실제 브라우저에서 접속해보도록 한다.
먼저 프로젝트 폴더로 이동하기 위해 터미널에서 
$ cd test 입력 후 엔터

그리고 npm을 통해 프로젝트를 실행하기 위해 터미널에서 
$ npm run serve 입력 후 엔터를 치면 정상설치가 되었을 경우 아래처럼 친절하게 접속 가능한 주소를 알려준다.

App running at:
  - Local:   http://localhost:8080/ 
  - Network: http://000.000.000.000:8080/
  Note that the development build is not optimized.
  To create a production build, run npm run build.

아무 브라우저나 열고 위 주소를 입력해보자

test로 생성해본 프로젝트 웹 접속 화면

여기까지 간단하게 처음 npm 설치부터 vue 테스트 프로젝트 설치 및 접속까지 알아보았다.

반응형
Posted by Hippalus
,

반응형

모 PG사의 파라메터들 중 한글을 포함한 파라메터를 넘길 때 UTF-8인 경우 encodeURIComponent를 호출하여 보내야만 했다.
웃긴건 이 PC사 모듈이 PC용이 있고 Mobile용이 있는데 PC용은 encode를 했다가 또다시 decode를 하는 코메디 상황을 연출한다란 점이다.
모바일은 더 웃긴게 encode만 한 후 결제 처리하는 페이지에서 다시 decode를 해야 한다란 점 -_-
도대체 왜 이딴식으로 개발하는지 PG사들 모듈들 보면 다년간 사람손을 많이 타와서 그런지 도무지 이해가 안가는 점이 한두개가 아니다.
왜들 그렇게 모듈을 만들 때 제대로 만들지 못하는건지
그나마 이 PG사는 일전에 망한 큰~기업 PG사에 비하면 양반이다.
그 큰 기업은 참.. 뭘 만들어도 이상한 결과물을 재생산해내는 노하우를 보유한 기업이니 이상하지 않지만 말이다.

javascript의 encodeURIComponent와 decodeURIComponent를 classic asp에서 호출할 때 runat server로 javascript함수를 호출해주면 된다.

<script language="javascript" runat="server">
    function decodeUTF8(str) {
        return decodeURIComponent(str);
    }

    function encodeUTF8(str) {
        return encodeURIComponent(str);
    }
</script>

<%
  response.write encodeUTF8(encodeFromJsString)
%>

반응형
Posted by Hippalus
,

반응형

www.w3schools.com/asp/ado_datatypes.asp

 

ADO Data Types

ADO Data Types The table below shows the ADO Data Type mapping between Access, SQL Server, and Oracle: DataType Enum Value Access SQLServer Oracle adBigInt 20   BigInt (SQL Server 2000 +)   adBinary 128   Binary TimeStamp Raw * adBoolean 11 YesNo Bit  

www.w3schools.com

 

TEXT type adLongVarChar

.Parameters.Append .CreateParameter("TEXTATA", adLongVarChar, adParamInput, len(TEXTDATA), TEXTDATA)    

 

NVARCHAR type adVarWChar

.Parameters.Append .CreateParameter("USERID", adVarWChar, adParamInput, 100, USERID)

반응형
Posted by Hippalus
,

반응형

새벽에 일어나보니 찬물이 안나온다. ㅎㅎㅎㅎ
이 아파트도 그랬고 지난번에 살던 아파트도 그랬던지라 뭐 당혹스럽거나 그렇진 않고 짜증만 좀 난다.

서울시에서 배포한 수도 동파 방지 비닐
이런거 해봤자 오늘같은 날씨엔 답 안나온다.
복도식 구축 아파트 사는 현실 ㅜㅜ 돈이 원수다.
동파가 10,20년 된 일도 아니거늘 애시당초 이런식으로밖에 건축 설계를 해버린 인간들 잘못이겠지만 -_-

동파방지 비닐을 뜯어보니 고작 이렇게 해놓고 덮어버렸나보다.
이러니 바로 얼어버렸지
이건 동파방지 한것도 안한것도 아니여

냉수만 안나오기 때문에 먼저 냉수 계량기가 어떤건지부터 확인해야했다.
윗계량기가 냉수일까 아랫계량기가 냉수일까
윗 수도 계량기를 열고 얼어버린 수도관을 만져보았다.
"싸늘하다. 가슴에 비수가 날아와 꽂힌다."
그렇다.
내가 사는 아파트는 윗 계량함이 냉수 계량함이었다.


이제부터 본격적인 10분안에 동파 수도 계량기 미션 스타트

방법은 간단하다.
미지근한 물보다 조금 더 뜨거운 물을 비닐에 붓고 혹시 모를 참사를 대비해 3중으로 재포장한다.
여기서 포인트는 비닐 봉다리 크기다.
욕심부리지 말고 계량기 사이즈 만큼 만들어야한다.
난 처음에 너무 커서 안들어가길래 주먹 두개 정도 크기로 만들었더니 쏙 들어갔다.
누구는 작게 여러개 넣어야 한다는데 대충 넣음 계량기 안에서 알아서 얼은 계량기를 녹여줄것이다.

준비한 온수 비닐 봉다리를 넣고 기다렸다.

이때가 3:38
동파가 해결됐는지 매번 체크하기 귀찮으니 찬물쪽으로 수도를 이빠이 틀어놓고

긴가 민가 정말 될까 의구심을 품은채 TV보고 있으니 곧이어 쏴!!! 시원한 물소리가 들린다.

위 사진은 이것저것 다 처리하고 찍은 사진이라 그런데 대충 5분 언저리로 걸렸다.

아침부터 서로 경쟁하듯 아파트 관리사무소에 연락하고 순서 기다릴 생각에 아찔했는데 온수 비닐 봉다리로 준비부터 동파 해결 미션 클리어까지 10분만에 해결했으니 끝이 좋으면 모든게 좋다.

우란 폐렴 코로나로 일년 내내 뭐같았는데
뻔뻔한 중국 태도에 가슴이 답답했는데
연말에 동파까지 당해 기분 다운됐는데
요래 해결하니 기분 좋아졌으~!

반응형
Posted by Hippalus
,

반응형

SELECT시 특정 필드를 CONVERT할 경우가 종종있다.
그런데 데이터 이상으로 해당 레코드들만 제외하고 CONVERT를 해야 할 경우 WHERE 조건을 준다한들 예외 오류가 발생하게 된다.

예를들어
퇴사일이 없는 (NULL값)직원이 있고 있는 직원이 있다치자
일괄적으로 CONVERT를 실행할 경우 여지없이 해당 NULL값인 직원의 데이터 때문에 예외 오류가 발생한다.
그러하다면 WHERE조건을 주고 해당 레코드들을 제외시킨 후 CONVERT를 하면 되겠거니 싶지만
여지없이 예외오류를 내뱉는다.
서브쿼리로 해당 테이블을 1차 가공 후 CONVERT를 실행시켜도 똑같다.

괴이한건 이 상황에서 그냥 TOP 1000000 을 주고 실행하면 오류를 발생시키지 않는다.
그렇다고 매번 TOP으로 실행하자니 못마땅하다.

이때 사용할 함수가 try_cast, try_convert, try_parse 되시겠다.

조금 더 구체적인 예로 try_convert 함수를 설명해 보겠다.

학생테이블인 STUDENT라는 테이블의 USERID 필드가 VARCHAR(50) 형태로 존재하고
아래처럼 해당 필드는 학번값을 저장하고 있다 치자

USERID
9201013
9201014
crazymyid94
student1101
0088341
0101003


그런데 특이하게 몇몇 레코드만 영문자로 되어 있는 상태고 학번의 앞자리 2자리를 기준으로 입학년도를 추출해야 할 상황인 경우
그냥 CONVERT쿼리를 실행하든 앞서 설명한 상황처럼 SUBQUERY, NOT IN, 알파벳을 제외하는 방법(not like '%[a-zA-Z]%') 등등
뭔짓을 해도 예외오류를 발생시킬 것이다.

메시지 245, 수준 16, 상태 1, 줄 15
varchar 값 'cr'을(를) 데이터 형식 int(으)로 변환하지 못했습니다.

이럴 땐 TRY_CONVERT함수를 WHERE문으로 실행시켜주면 깔끔하게 해결된다.
SELECT USERID FROM STUDENT WHERE TRY_CONVERT(INT, LEFT(USERID, 2)) <= 99

반응형
Posted by Hippalus
,