본문 바로가기

보이지 않는 더 넓은 세상💻/개발인지 개🐕발인지

보편적이지 않은 개발#3] 구글 스프레드 시트를 DB처럼 이용해보자


ⓒopenicons pixabay.com

HTML을 기반으로 만든 나 스스로가 웹앱(?)이라 부르는 간단한 초진 작성기를 완료하였다. 차트 입력만을 위해서 실컷 입력만하고 외래를 보다보면, 추후 데이터 수집할 때 2번의 일이 필요하다. 늘 전공의때 이런 일로 힘들었다. 그래서 차트를 작성하면서 데이터베이스로 저장하는 방식에 대해서 늘 고민이 많았다. SQL 에 대해서 공부했지만, 간단한 앱을 만드는데 SQL에 서버 호스팅까지 하려니 이건 배보다 배꼽이 큰 격이었다. 우연히 검색하다가 구글 spreadsheet를 이용하면 간단한 DB처럼 이용할 수 있다는 내용을 보고 언젠가 만들어야지 언젠가 만들어야지 미루다보니 벌써 6개월 정도가 지나버렸다. 드디어 그 작업을 완료하게 되어서, 기록으로 남겨 놓는다.

결과

클릭하면 확대됩니다

 


이번 작업의 목표는 HTML로 제작한 form에 입력된 자료를 DB로 만드는게 목표였다. 구글 spreadsheet를 이용할 예정이었고, 아래 영상에서 잘 나와있다.

 

다른 몇몇 영상들은 "id=entry_XXXXXXXXXXX"로 되어있어서 작동이 안되는 것 같았고, jquery를 이용하여 ajax로 하는 방법도 있었지만, 이 방법이 가장 간단하여서 택하였다. (사실 ajax를 잘 다루지 못한다...) 동영상에 잘 나와있지만 내용을 간단하게 요약해보면 아래와 같다.

  • 구글 form을 이용하여 설문지 form을 만든다. 이 때 항목은 본인의 database schema를 생각해서, 수집할 데이터가 무엇인지를 결정해서 만들면 된다. 나는 "통증부위, 좌우, 외상여부, 외상이유, 통증기간, VAS" 6개의 항목으로 결정하였다. (추후 변경이 가능하다)
  • 설문지 form에서 control +shift +I(요소검사)를 해보면 <form 이라는 곳에 보면, url이 나오게 되는데 이 주소가 바로 내가 POST방식으로 쿼리를 보내야할 url이다. 
  • 아래의 코드는 가장 기본 형식으로 되어있는 내용이다. 요소검사에서 각각에 해당하는 name을 찾아서 form에 name에 입력해주면, form에 입력된 자료는 entry.XXXXXX라는 구글 스프레드시트항목에 입력되게 된다. 

form action="url" method="POST" target="_blank"

실제 적용

하지만, 실제 적용은 역시 쉽지 않았다. 하면서 겪었던 내용들 중 해결한 방법은 아래와 같다.

  • name으로 entry.XXXXXXXXXX로 입력하니 parsing이 잘 안되는 항목이 있어서 id와 name 모두를 entry.XXXXXXXX로 변경하였다.
  • name이 여러 개인 경우에는, spreadsheet에 저장될 때 ",(comma)"로 구분되며 추가된다. (추후 해결해야함)
  • form 을 submit할 때마다 새로운 창이 생기거나 (target="_blank"), 기존의 창에서 변경되게 되어서 (target="_self") target="resultIframe"라는 내용을 입력하였다. ""안에 frame의 "name"을 입력하면 iframe 태그가 있는 곳에서 해당 결과페이지가 iframe 방식으로 열리게 된다.

이 부위에서 열리게 되고 화면에서 보기 싫으면 CSS 속성을 hidden으로 해서 가리면 된다.


<!doctype html>
<html>
<head>
<meta charset='UTF-8'><meta name='viewport' content='width=device-width initial-scale=1'>

</head>
<style>
body{
  font-family:'Nanum Gothic', sans-serif;
  background-image:url('https://source.unsplash.com/user/impatrickt');
  background-size:100%;
}
.blank25{
  height:25px;

  }
.content-wrap{
  background-color:white;
  margin-left:auto;
  margin-right:auto;
  width :550px;
  border: 3px solid #333333;
  padding: 20px;
  border-radius:5px;

}
.my-content{
  font-size:20px;
  line-height:1.8em;
}
.my-range{
  font-size:20px;
}
.my-content input[type=radio],.my-content input[type=checkbox]{
/* Double-sized Checkboxes */
  -webkit-transform: scale(2); /* Safari and Chrome */
  margin: 10px;
}
input[type="button"]{
margin-top:20px;
padding: .5rem 1rem;
font-size: 1.25rem;
line-height: 1.5;
border-radius: .3rem;
color: #fff;
    background-color: #007bff;
    border-color: #007bff;
    width: 300px;
}
input[type="reset"]{
padding: .5rem 1rem;
font-size: 1.25rem;
line-height: 1.5;
border-radius: .3rem;
color: #fff;
}

input[type=range]{
    -webkit-appearance: none;
    width:250px;
}
input[type=range]::-webkit-slider-thumb {
    -webkit-appearance: none;
    border: 3px solid white;
    height: 20px;
    width: 20px;
    border-radius: 50%;
    background: red;
    margin-top: -4px;
}
input[type=range]::-webkit-slider-runnable-track {
    width: 500px;
    height: 10px;
    background: #ddd;
    border: none;
    border-radius: 3px;
}
input[type=range]:focus {
    outline: none;
}
input[type=range]:focus::-webkit-slider-runnable-track {
    background: #ccc;
}


input[type="reset"]{
  background-color: white;
  color: #333333;
}
textarea {
  border:2px solid black;
  width: 92%;
    border-radius:5px;
    padding:20px;
    font-size:1rem;
    font-weight:700;
    font-family:'Nanum Gothic', sans-serif;
}


input[type=range]:focus::-webkit-slider-runnable-track {
  background: #367ebd;
}

@media screen and (max-width:500px){
  .content-wrap{

  }
  .my-content{
      font-size:15px!important;
  }
  .my-content input[type=radio],.my-content input[type=checkbox]{
  /* Double-sized Checkboxes */
    -webkit-transform: scale(1.5); /* Safari and Chrome */
    margin: 8px;
}
.content-wrap{
  width :90%;
  padding: 1rem;
  border-radius:5px;

}
}

</style>
<script>
function myFunction(){

//오늘 날짜 확인
  var date = new Date(); //매개변수가 없는 경우 현재 날짜와 시간을 가지는 인스턴스를 반환한다.
   var month = date.getMonth() + 1; // 0부터 시작하므로 1더함 더함
   var day   = date.getDate();

   if (("" + month).length == 1) { month = "0" + month; }
   if (("" + day).length   == 1) { day   = "0" + day;   }
   var printedDate = month +'-'+day;
  <!-- 아래 부분은 통증 위치 파악-->
    var Location = ""
    for(var i=0; i<19; i++){
     if(document.getElementsByName("entry.268954659")[i].checked == true){

       var Location = Location + document.getElementsByName("entry.268954659")[i].value
     }};

//


//아래 부분은 통증 좌우 파악
  var Lesion=""
  for(var i=0; i<3; i++){
   if(document.getElementsByName("entry.115438232")[i].checked == true){
     var Lesion = document.getElementsByName("entry.115438232")[i].value
   }};


// 아래 부분은 외상 여부 파악
var Trauma=""
var TraumaReason= document.getElementById("entry.2066414521").value
var TraumaDuration= document.getElementById("entry.838521009").value
for(var i=0; i<2; i++){
 if(document.getElementsByName("entry.1861609866")[i].checked == true){
   var Trauma = document.getElementsByName("entry.1861609866")[i].value
 }};


//아래 부분은 VAS 파악

   var VAS=document.getElementById("vas-range").value;


   var printedResult= Location +' '+ Lesion+' '+Trauma+' '+TraumaReason+' , '+ TraumaDuration+' , VAS: '+VAS +'\n'+   'SB(+)'+'\n'+printedDate ;
   document.getElementById("myResult").innerHTML= printedResult;

//아래는 결과 트리밍
printedResult=printedResult.replace('  ',' r');

//결과 클립볻드로 복사
 copy_to_clipboard();
};

function copy_to_clipboard() {
     var copyText = document.getElementById("myResult");
     copyText.focus();
     copyText.select();
     document.execCommand("Copy");
   }

</script>




<body>
<div class="blan25"></div>
<div class="content-wrap">
  <h1> 초진 기록지 for BM by BM </h1>
      <form action="https://docs.google.com/forms/d/e/1FAIpQLSe4nJ1TXTJrVuR8gpM3a5myVxJDyw8DG3ERjTKvgibrUk0Rhg/formResponse"
      target="resultIframe" method="POST" >
          <div class="my-content">
            <div name="my-pain-location">

              <input type="checkbox" name="entry.268954659" value="목,">목
              <input type="checkbox" name="entry.268954659" value="어깨,">어깨
              <input type="checkbox" name="entry.268954659" value="어깨죽지,">어깨죽지
              <input type="checkbox" name="entry.268954659" value="허리,">허리
              <input type="checkbox" name="entry.268954659" value="등,">등
              <input type="checkbox" name="entry.268954659" value="갈비뼈,">갈비뼈 <br>
              <input type="checkbox" name="entry.268954659" value="엉덩이,">엉덩이
              <input type="checkbox" name="entry.268954659" value="고관절,">고관절
        <input type="checkbox" name="entry.268954659" value="허벅지,">허벅지
              <input type="checkbox" name="entry.268954659" value="무릎,">무릎
              <input type="checkbox" name="entry.268954659" value="종아리,">종아리<br>
              <input type="checkbox" name="entry.268954659" value="발목,">발목
              <input type="checkbox" name="entry.268954659" value="발가락,">발가락
              <input type="checkbox" name="entry.268954659" value="발바닥,">발바닥
              <br>
              <input type="checkbox" name="entry.268954659" value="손가락,">손가락
              <input type="checkbox" name="entry.268954659" value="팔꿈치,">팔꿈치
              <input type="checkbox" name="entry.268954659" value="손목,">손목
               <input type="checkbox" name="entry.268954659" value="손바닥,">손바닥
              <input type="checkbox" name="entry.268954659" value="lower arm,"> lower arm
         </div>

        <hr>
            <div name="my-pain-lesion">
                <input type="radio" name="entry.115438232" value="-/+,">좌
                <input type="radio" name="entry.115438232" value="+/-,">우
                <input type="radio" name="entry.115438232" value="+/+,">양측
            </div>

            <div name="my-trauma">
                <input type="radio" name="entry.1861609866" value="외상(-)" checked>외상 없음
                <input type="radio" name="entry.1861609866" value="외상(+):">외상 있음
                <input type="text"  id="entry.2066414521" name="entry.2066414521" placeholder="이유를 입력하세요" value=""
                       minlength="1" maxlength="200" size="50" height="30px" style="line-height: 30px;"><br>
                <input type="text"  id="entry.838521009" name="entry.838521009" placeholder="통증 기간을 입력하세요" value=""
                              minlength="1" maxlength="200" size="30" height="30px" style="line-height: 30px;">
            </div>




            <div class="my-range">
                  VAS   <input oninput = 'ShowSliderValue(this.value)' id="vas-range" name="entry.894327154" type = "range" min='0' max='10' value='4' step='2'>
                        <span id="slider_value_view">4</span>점

                                  <script language = "javascript">
                                    function ShowSliderValue(sVal)
                                    { 	var obValueView = document.getElementById("slider_value_view");
                                  	  obValueView.innerHTML = sVal
                                    }
                                  </script>
            </div>
</form>
            <div id="submission-hc">
                        <input type="button" class="btn-yes" value="결과" onclick="myFunction()">
                        <input type="reset" value="새로고침">
            </div>


        <div id="result" >
        <hr>
         <textarea id="myResult"  rows="8" style="white-space:pre;">위의 결과를 누르시면 결과가 클립보드로 복사됩니다.</textarea>
       <input type="submit" value="DB저장">
       <a href="https://docs.google.com/spreadsheets/d/110hSXYRHLGlu5osJQTiGeQ6T48NEtr3pY1kS9pnmzTk/edit?usp=copy" target="_blank" style="text-decoration:none;"> <span style="border:1px solid grey; background-color:#ddd; padding: 2px; font-size:14px;">DB 보기 </span></a>
       <iframe name="resultIframe"width="100%" height="50px">iframe</iframe>

       </div>
</div>




</body>
</html>

참고 사이트>

1. https://www.youtube.com/watch?v=eVvhNAnOf1A

2. form target="framename"을 이용하여 form의 내용을 submit 하더라도 다른 페이지로 연결되지 않게 하는 법

 

IFRAME 에 Post 형식으로 데이터 보내기

iframe에 post 방식으로 데이터를 전송하려면 다음과 같이 한다. 1. 전송하고자 하는 iframe에 id가 아닌 name을 부여한다. 2. form에서 target으로 해당 iframe의 name을 지정한다. - 단. 이때 반드시 " 쌍따옴표..

gense.tistory.com

 

♡를 눌러주시면 블로그를 작성하는데 큰 힘이 됩니다♪
로그인이 필요없어요.

이 블로그 인기글