Nueva publicación

Rechercher

Artículo
· 29 mayo, 2025 Lectura de 8 min

Integrate with Google Forms

Google Forms is the most popular solution on the market for collecting data, answering questionnaires and quizzes. So, it is the ideal solution for collecting patient data and responses in a practical way, without the need to expand or develop systems. In this article, I will detail how to create an account on Google Cloud, register the application that will consume the Google Forms API, generate the service user necessary to consume the API and finally perform actions to create new forms and collect data filled in them in an automated way in embedded Python and IRIS.

Create your Google Cloud account

If you don’t have Google Cloud account, follow these steps, otherwise go to the next section.
To create a Google Cloud Platform (GCP) account, you first need a Google account. Then, you can sign in to the Google Cloud console and start using the free tier or create a paid account. Here's a step-by-step guide:

1.    Go to the Google Cloud console: Visit cloud.google.com.
2.    Sign in with your Google account: If you don't have one, you'll need to create one.
3.    Accept the terms and conditions: Review and accept the Google Cloud terms and conditions.
4.    Start Free or Create a Billing Account:
a.    Free Tier: You can start using Google Cloud for free with the free tier.
b.    Paid Account: If you need more resources or advanced features, you'll need to create a billing account.
5.    Create a Billing Account (if needed): If you choose to create a paid account, you'll need to set up a billing account, which requires providing payment verification details and information about your organization.
6.    Get Started: Once your account is set up, you can access the Google Cloud console and start using the services.   

Create a Google Cloud project
 

It is mandatory to create a project to use Google APIs and SDKs into your programs.
Go to this link and follow the steps: https://developers.google.com/workspace/guides/create-project

 

Create a Google Cloud Service Account

It is required create a service account (credentials for applications) to your application consume the Google Forms API.

1.    Go to https://console.cloud.google.com/projectselector2/iam-admin/serviceaccounts , select the project that you selected in the previous section.
2.    Click the button + Create service account, fill the required fields and click the button Create and continue.
3.    Select the role Owner and click the Continue button.
4.    Save your Credentials JSON file to use later.
5.    Click the button Done.
6.    Click the button 3 dots and select Manage keys:
 
7.    Click the button Add key > Create new key
8.    Select JSON and click Create:
 
9.    The credentials are saved into your downloads page, SAVE THIS FILE BECAUSE I WILL USE IT LATER.


Enable Google Forms and Google Drive APIs

To your project consume the Google Forms and Google Drive (because Drive store the Google Forms definitions), you must enable the access:
1.    Go to https://console.cloud.google.com/apis/dashboard
2.    Click the button + Enable APIs and services
3.    Search for Google Drive API on the top field Search for APIs & Services, select Google Drive API and enable the API, if not enabled yet.
4.    Repeat the step 3 and Search for Google Forms API on the top field Search for APIs & Services, select Google Forms API and enable the API, if not enabled yet.


Get and run the health-gforms project

I created a sample application (health-gforms at https://openexchange.intersystems.com/package/health-gforms) that create a Google Form and collect data from it.


1.    Clone/git pull the repo into any local directory
$ git clone https://github.com/yurimarx/health-gforms/health-gforms.git
2.    Open the terminal in this directory and run:
$ docker-compose build
$ docker-compose up -d

 

Using the health-gforms API via Postman


1.    Download (https://www.postman.com/downloads/) and install the Postman application, if you don’t have this application yet.
2.    Download the postman collection from https://github.com/yurimarx/health-gforms/raw/refs/heads/master/health-g...
3.    Import this collection into your Postman:
 
4.    Click the 1. Post credentials to upload the google cloud service account credentials into your docker instance:
 
5.    Click the 2. Post form definition, to save the form definition (use a file from our root project folder, formpatient.json) into our docker instance:
 
6.    Click 3. Create form from file definition, to create a new google form on Google cloud and to collect data about a new patient:
 
7.    Copy the value into formId:
 
8.    Open the Google forms using your browser (pay attention for formId value, I used it into the path: https://docs.google.com/forms/d/1DtqV5edXVOjM-FAntPffRHqfVjMjOIJuiq5VXBc...
 
9.    To fill the Google Forms as end user, go to the button participant link   and past in a new browser tab:
 
10.    Fill the form as end user:
 
11.    Post the form answers.
12.    Click the 4. Get form content from template and change the value formId with the formId provided in the step 7:
 
13.    Click the send button and see the fhir json content to send to your FHIR server:

 

Behind the Scenes

Creating a Form into Google Forms:

ClassMethod CreateFormFromFile(formtitle As %String, filepath As %String) [ Language = python ]
{
    
    import httplib2
    import json
    from oauth2client.service_account import ServiceAccountCredentials
    from googleapiclient.discovery import build
    from mako.template import Template

    
    credentials = ServiceAccountCredentials.from_json_keyfile_name(
        "/opt/irisapp/credentials.json",
        scopes=["https://www.googleapis.com/auth/forms.body", 
                "https://www.googleapis.com/auth/forms", 
                "https://www.googleapis.com/auth/drive", 
                "https://www.googleapis.com/auth/drive.file"],
    )

    http = httplib2.Http()
    http = credentials.authorize(http)

    form_service = build("forms", "v1", http=http)

    new_form_template = Template('{"info": {"title": "${title}"}}')
    new_form_str = new_form_template.render(title=formtitle)
    NEW_FORM = json.loads(new_form_str)

    # Create the form
    try:
        result = form_service.forms().create(body=NEW_FORM).execute()
        formid = result["formId"]
        print(f'Form created: {result}')

        with open(filepath) as file:
            itemsjson = json.loads(file.read())
            # Adds form items
            items = (
                form_service.forms()
                .batchUpdate(formId=formid, body=itemsjson)
                .execute()
            )

        permission2 = {
            'type': 'anyone',
            'role': 'writer',
        }

        drive_service = build('drive', 'v3', credentials=credentials)

        drive_service.permissions().create(fileId=formid, body=permission2).execute()

        return formid
    except Exception as e:
        print(f'Error creating form: {e}')
}

1. We create the credentials using the service account data inside a credentials json file for form and drive apis.

2. We use this credentials to build a form_service.

3. The form_service is used to create the Google Form with header only.

4. The form_service reads the formpatient.json to create the forms itens (fields or questions). See this file content:

{
    "requests": [
        {
            "createItem": {
                "item": {
                    "title": "Given Name",
                    "questionItem": {
                        "question": {
                            "required": true,
                            "textQuestion": {}
                        }
                    }
                },
                "location": {"index": 0}
            }
        },
        {
            "createItem": {
                "item": {
                    "title": "Family Name",
                    "questionItem": {
                        "question": {
                            "required": true,
                            "textQuestion": {}
                        }
                    }
                },
                "location": {"index": 1}
            }
        },
        {
            "createItem": {
                "item": {
                    "title": "Gender",
                    "questionItem": {
                        "question": {
                            "required": true,
                            "choiceQuestion": {
                                "type": "RADIO",
                                "options": [
                                    {
                                        "value": "male"
                                    },
                                    {
                                        "value": "female"
                                    }
                                ]
                            }
                        }
                    }
                },
                "location": {"index": 2}
            }
        },
        {
            "createItem": {
                "item": {
                    "title": "Birth Date",
                    "questionItem": {
                        "question": {
                            "required": true,
                            "dateQuestion": {
                                "includeYear": true
                            }
                        }
                    }
                },
                "location": {"index": 3}
            }
        },
        {
            "createItem": {
                "item": {
                    "title": "Phone",
                    "questionItem": {
                        "question": {
                            "required": true,
                            "textQuestion": {}
                        }
                    }
                },
                "location": {"index": 4}
            }
        }
    ]   
}

5. Now we have a new form.

Collect user data responses from a Google Form:

ClassMethod GetResponsesFromFormId(formid As %String) [ Language = python ]
{
    import httplib2
    from oauth2client.service_account import ServiceAccountCredentials
    from googleapiclient.discovery import build

    credentials = ServiceAccountCredentials.from_json_keyfile_name(
        "/opt/irisapp/credentials.json",
        scopes="https://www.googleapis.com/auth/forms.responses.readonly",
    )

    # Create an httplib2.Http object to handle our HTTP requests and authorize
    # it with the Credentials.
    http = httplib2.Http()
    http = credentials.authorize(http)

    form_service = build("forms", "v1", http=http)

    # Prints the responses of your specified form:
    result = form_service.forms().responses().list(formId=formid).execute()
    return result
}

1. A credential object is created using the service account defined into credentials.json with authorization to read google forms.

2. A form_service is created from the credentials.

3. The form_service is used to get all responses from a formId.

2 comentarios
Comentarios (2)1
Inicie sesión o regístrese para continuar
Anuncio
· 29 mayo, 2025

InterSystems Ideas News #22

Hi Community!

Welcome to Issue #22 of the InterSystems Ideas newsletter! This edition highlights the latest news from the Ideas Portal, such as:

✓ General Statistics
✓ Recently implemented ideas
✓ New features

   Here are some April numbers for you. During this month, we had:

  • 11 new ideas
  • 2 implemented idea
  • 18 comments
  • 29 votes

👏 Thanks to everyone who contributed in any way to the Ideas Portal last month.

   In recent months, several of your ideas have been implemented by both other Developer Community members and InterSystems. Here they are:

   Aha platform had a recent update, and now our Ideas Portal has some new cool features! 

It now supports user mentions in comments and allows you to like comments you find helpful or relevant. Look out for a standalone announcement on how it works very soon!


✨ Share your ideas, support your favorites with comments and votes, and bring the most interesting ones to life!

Comentarios (0)1
Inicie sesión o regístrese para continuar
Artículo
· 29 mayo, 2025 Lectura de 8 min

Génération d'une classe ObjectScript à partir d'une réponse JSON à l'aide de ChatGPT

J'ai un nouveau projet qui consiste à stocker des informations provenant de réponses REST dans une base de données IRIS. Il me faudra synchroniser les informations provenant d'au moins deux douzaines de points de terminaison REST distincts, ce qui implique la création de presque autant de classes ObjectScript pour stocker les résultats de ces points de terminaison.

Comentarios (0)2
Inicie sesión o regístrese para continuar
Pregunta
· 29 mayo, 2025

How to reset the Web Gateway management Password

I am trying to log in to the Web Gateway Management and I have missed placed the password to access the system I have tried 

changing the password under local settings in the CSP.ini  and that has managed to change the password to access the gateway but cannot log me into the management area I have followed a post here and read here and I seem not to get the answers that actual explain how I can get to the web gateway management.

I understand that changing the user in the management portal does not change the password set up in the installation to access the web management gateway if anyone has had to deal with this please advice. 

3 comentarios
Comentarios (3)3
Inicie sesión o regístrese para continuar
Artículo
· 29 mayo, 2025 Lectura de 6 min

InterSystems製品のロックの基本

これは InterSystems FAQ サイトの記事です。

InterSystems製品では、複数のプロセスが同時に同じデータにアクセスする場合、排他制御を行うためにロックを使用できます。
ロックは、データの更新を正しく行い整合性を保つための仕組みで、あるデータに対する更新処理を制御するために使用します。
ロックを操作するには、LOCK(L)というコマンドが使用できます。

こちらの記事では、InterSystems製品で使用できるロックの種類、LOCKコマンドの使い方をご紹介します。


★ロックの種類

  増分 単純
排他(既定) LOCK +^A LOCK ^A
共有 LOCK +^A#"S" LOCK ^A#"S"


プラス記号 (+) をつけると、増分ロックになります。1つのプロセスで複数の増分ロックを追加できます。
プラス記号 (+) をつけないと、単純ロックになります。こちらは、1つのプロセスで1つのロックのみ所有できます。単純ロックコマンド実行時に既存のロックがあった場合、そのプロセスが保持している既存のロックをすべて削除し、新しいロックを追加します。

排他ロック
データを更新するために使用するロックです。
プロセスが特定のロック名の付いた排他ロックを所有している時、その他のプロセスは、そのロック名の付いたロックを取得できません。
SQLでいうと、INSERT, UPDATEやDELETE文の実行時にかかります。

共有ロック
データを参照していることを示すためのロックです。
プロセスが特定のロック名の付いた共有ロックを所有しているときに、その他のプロセスは、そのロック名の付いた共有ロックを取得できます。ただし、その他のプロセスはそのロック名の付いた排他ロックを取得できません。
SQLでいうと、Read Committed モードでの SELECT文の実行時にかかります。


★ロックの方法

ロックを追加する(lockname:ロック名※、locktype:後述)
※ロック名は任意の名前ですが、共通の規則としてロックする項目(グローバル・変数等)の名前と同じロック名を使用します。

LOCK +lockname#locktype

ロックを削除(解放)する

LOCK -lockname#locktype

使用例:

(A)   Lock ^a		// このコマンドを実行すると、^bだけが最終的に残ります
      Lock ^b		// ※Lock ^b  だけの場合、ほかのロックを全て解放した後、^bだけロックを持ちます
(B)   Lock +^a		// このコマンドを実行すると、^a,^bの二つロックが残ります。
      Lock +^b

尚、正常に終了したプロセスは取得していたロックを全て解放します。 


★ロックタイプ(locktype)

 S — 共有ロックを追加します。"排他ロックと共有ロック" を参照してください。
 E — エスカレートロックを追加します。"非エスカレート・ロックとエスカレート・ロック" を参照してください(後述)。
 I — 即時アンロックタイプでロック解除を行います。
 D — 遅延アンロックタイプでロック解除を行います。

※エスカレートロック
大量のロックを管理するためにエスカレートロックを使用します。
これは配列のノードをロックする場合に使用されます。例えば、同じ添え字レベルで複数のノードをロックする場合です。

ロックのエスカレーションの例(テーブルロック)
こちらの記事 でテーブルロックの例を紹介しておりますので、参考になさってください。


★ロック管理ユーティリティでできること

次のユーティリティでロックの管理が行えます。

1. 管理ポータルを使用する方法
 ⇒ 管理ポータル:システムオペレーション > ロック > ロックを表示(または管理)

2. ^LOCKTAB ユーティリティ を使用する方法
 ⇒ %SYS>do ^LOCKTAB

3. プログラムを使用する方法
 ⇒ プログラム内でロック情報を取得する方法

これらのユーティリティでは、主にロックの参照・解放(削除)が行えます。
ロックテーブルの参照方法については、関連トピック ロックテーブルの参照方法とその見方 をご覧ください。

以下にそれぞれのユーティリティを使用した、ロックの削除方法をご紹介します。
 

☆ロックの削除手順(1の管理ポータルで行う方法)

管理ポータル:システムオペレーション > ロック > ロックを管理
→ 該当ロックの「削除」リンクより削除を行います。

 


☆ロックの削除手順(2の ^LOCKTAB ユーティリティで行う場合)

%SYS>do ^LOCKTAB
:
                           Node Name: XXX
                   LOCK table entries at 05:22PM  03/06/2025
               308464608 bytes usable, 308472544 bytes available.
 
Entry Process     X#   S# Flg   W# Item Locked
   1) 39740        1               ^["^^c:\intersystems\iris\mgr\"]ISC.LMFMON("License Monitor")
:
   8) 30100        1             1 ^["^^c:\intersystems\iris\mgr\user\"]A
Waiters: 25164(XE)
 
Command=> D           // 削除の時は D を入力
Entry to delete: 8    // 削除したいロックの番号を入力 + <Enter>
   8) 30100        1          ^["^^c:\intersystems\iris\mgr\user\"]A
Are you sure you want to delete this lock? No => yes  // Y(y) を入力+<Enter> でロックが削除される
Entry to delete:      // 以下、Q + <Enter> で抜ける


☆ロックの削除手順(3のプログラムで行う場合)

  // プロセスID=2004 が所有するすべてのロックを削除する
  Set rc=##Class(SYS.Lock).DeleteAllLocks(2004)
   
  // リモートクライアントシステム 'SystemA' が所有するすべてのロックを削除する
  Set rc=##Class(SYS.Lock).DeleteAllLocks("CSystemA")
  
  /// ロック名やプロセスを指定して削除する
  // ^|"^^c:\intersystemsdb\mgr\user"|a(1) ロックを削除する
  Set rc=##Class(SYS.Lock).DeleteOneLock("^|""^^c:\intersystemsdb\mgr\user""|a(1)")
   
  // プロセスID=2004 が所有する ^|"^^c:\InterSystemsdb\mgr\user"|a(1) ロックを削除する
  Set rc=##Class(SYS.Lock).DeleteOneLock("^|""^^c:\intersystemsdb\mgr\user""|a(1)",2004)


★ロックテーブル サイズの変更

以下メニューからロックテーブルのサイズを変更できます。

管理ポータル:
 [システム管理] > [構成] > [追加の設定] > [メモリ詳細設定] → locksiz

※バージョン2023.1以降では、デフォルト値は0でシステムに最適な値が割り当てられます。
 この場合、gmheap パラメータで指定された共有メモリサイズのみでこのサイズが制限されます。
※ロックテーブルサイズを変更する場合は、gmheapサイズもあわせて変更します。
※ロックテーブルが一杯になるとコンソールログに、以下のようなエラーメッセージが表示されます。
 02/08/25-00:05:09:248 (20093) 2 [Generic.Event] LOCK TABLE FULL!!!  (Repeat messages will be suppressed for 20 minutes). 
 ロックコマンド自体はエラーにはならず待ち状態になります(^LOCKTABには表示されません)。
 

enlightened【ご参考】
適正なロックテーブルサイズの算出方法
ロックテーブルの使用状況を簡単に確認する方法
SQLのUPDATEやDELETEで、ある程度の数のレコードを一括更新するとSQLエラー -110 が発生します。
SQLでレコードをSelectするとSQLエラー -114 が発生します
現在の一般メモリヒープ(gmheap)と取得可能なロックテーブル(locksiz)最大サイズについて
ロックテーブルの参照方法とその見方

Comentarios (0)0
Inicie sesión o regístrese para continuar