LoginSignup
5
1

More than 1 year has passed since last update.

Asana のあるプロジェクトから未完了タスクの一覧を出す

Posted at

Python で Asana から未完了タスクの一覧を出す方法を紹介します。

ここでは、 Python で、スプレッドシートに貼り付けるためのデータを取得します。

作りたい表の形

Asanaのタスクから、次のようなスプレドシートの表を作ることにします。

Section Task Status
セクション1 タスク1 ステータス1
セクション1 タスク2 ステータス1
セクション1 タスク3 ステータス2
セクション1 タスク4 ステータス2
セクション2 タスク5 ステータス1
セクション2 タスク6 ステータス1
セクション2 タスク7 ステータス2
セクション2 タスク8 ステータス2
セクション3 タスク9 ステータス2
セクション3 タスク10 ステータス3

環境

  • Python 3.9.0
  • pyperclip
  • asana

コード

一連のコードです。

PERSONAL_ACCESS_TOKEN='XXXXXXXX'
PROJECT_ID='XXXXXXXX'

import asana

client = asana.Client.access_token(PERSONAL_ACCESS_TOKEN)

def find_sections(project_id):
    result = client.sections.get_sections_for_project(project_id, {}, opt_pretty=True)
    return result

def find_tasks(project_id): 
    result = client.tasks.get_tasks(
        {
            'completed_since': 'now',
            'opt_fields' : [
                'this.name', 'this.due_on',
                'this.custom_fields',
                'this.assignee',
                'this.assignee.name',
                'this.memberships.section',
                'this.memberships.section.name'
            ],
            'project': project_id
        },
        opt_pretty=False
    )
    return result

section_ids = [section['gid'] for section in find_sections(PROJECT_ID)]

text = 'Section\tTask\tStatus\n'
# i = 1
for task in find_tasks(PROJECT_ID):
    sections = list(
        filter(
            lambda x: x['section']['gid'] in section_ids,
            filter(lambda x: 'section' in x, task['memberships'])
        )
    )
    section = sections[0]['section'] if len(sections) > 0 else None

    statuses = list(filter(lambda x: x['gid'] == '1234567890123456', task['custom_fields']))
    status = statuses[0]['enum_value'] if len(statuses) > 0 else None

    # if i == 1:
    #    print(task['custom_fields'])
    #    i += 1

    text += f'{section["name"] if section is not None else None}\t' + \
        f'{task["name"]}\t' + \
        f'{status["name"] if status is not None else None}'
    text += "\n"

import pyperclip
pyperclip.copy(text)

説明

まずアクセストークンとプロジェクトIDを格納します。

PERSONAL_ACCESS_TOKEN='XXXXXXXX'
PROJECT_ID='XXXXXXXX'

Asana のクライアントを作ります。

import asana

client = asana.Client.access_token(PERSONAL_ACCESS_TOKEN)

クライアントを利用して、あるプロジェクト内のセクションの一覧と、あるプロジェクト内のタスクの一覧を取得する関数を作ります。
タスクの一覧を取得するときに、セクション名も取れるのですが、そのときにタスクが複数のセクションに所属していると、それらがすべて取得できてしまいます。
そういった場合に、表示するべきセクションを絞り込むために、あるプロジェクトないのセクションを一度取得しています。

find_tasks では、 完了日の条件のみを指定しています。
タスクの基本情報と一緒に取得したいデータを、 opt_fields に設定しています。 どんなフィールドが使えるのかは、 get_task の レスポンスの構造を見るとわかります。

def find_sections(project_id):
    result = client.sections.get_sections_for_project(project_id, {}, opt_pretty=True)
    return result

def find_tasks(project_id): 
    result = client.tasks.get_tasks(
        {
            'completed_since': 'now',
            'opt_fields' : [
                'this.name', 'this.due_on',
                'this.custom_fields',
                'this.assignee',
                'this.assignee.name',
                'this.memberships.section',
                'this.memberships.section.name'
            ],
            'project': project_id
        },
        opt_pretty=False
    )
    return result

セクションをすべて取得して、そのIDをリストにしておきます。
その後、プロジェクト内の未完了タスクをすべて取得して、表示する項目を整理して、 text にタブ区切りの文字列を生成します。

section_ids = [section['gid'] for section in find_sections(PROJECT_ID)]

text = 'Section\tTask\tStatus\n'
# i = 1
for task in find_tasks(PROJECT_ID):
    sections = list(
        filter(
            lambda x: x['section']['gid'] in section_ids,
            filter(lambda x: 'section' in x, task['memberships'])
        )
    )
    section = sections[0]['section'] if len(sections) > 0 else None

    statuses = list(filter(lambda x: x['gid'] == '1234567890123456', task['custom_fields']))
    status = statuses[0]['enum_value'] if len(statuses) > 0 else None

    # if i == 1:
    #     print(task['custom_fields'])
    #     i += 1

    text += f'{section["name"] if section is not None else None}\t' + \
        f'{task["name"]}\t' + \
        f'{status["name"] if status is not None else None}'
    text += "\n"

ここで status は、カスタマイズとして追加されたフィールドです。
カスタマイズされたフィールドは、 taskcustom_fields に含まれて返ってきます。
そこで、表示したいカスタムフィールドの gid で値をフィルタ・表示しています。

コメントアウトされている箇所をコメントインすると、 カスタムフィールドの一覧が表示されるので、gid を調べることができるようになります。

最後に、組み立てた文字列をクリップボードにコピーします。

import pyperclip
pyperclip.copy(text)

コピーした文字列を Excel などに貼り付けると、 表として表示されます。

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1