����λ�ã���ҳ > �����̳� > �̳� > ����Ӧ�ÿ���-Python���������ĵ���excel�棩

����Ӧ�ÿ���-Python���������ĵ���excel�棩

��Դ������������|��ʱ�䣺2024-07-04 15:35:29 |���Ķ���191��|�� ��ǩ�� T El C ���� ���� excel Ӧ�� Python �� |����������

����Ӧ�ÿ���-Python���������ĵ� һ�� �����SDK���� �����SDK���� - ��������ƽ̨ (dingtalk.com) pip3 install alibabacloud_dingtalk ������������ƽ̨ �����ߺ�̨ (dingtalk.com) �������� - ��������ƽ̨ (dingt

����Ӧ�ÿ���-Python���������ĵ�

һ�� �����SDK����

�����SDK���� - ��������ƽ̨ (dingtalk.com)

pip3 install alibabacloud_dingtalk

������������ƽ̨

�����ߺ�̨ (dingtalk.com)

�������� - ��������ƽ̨ (dingtalk.com)

2.1������Ӧ��

¶¤¶¤Ó¦Óÿª·¢-Python²Ù×÷¶¤¶¤Îĵµ£¨excel°æ£©

¶¤¶¤Ó¦Óÿª·¢-Python²Ù×÷¶¤¶¤Îĵµ£¨excel°æ£©

2.2����ȡӦ�û�����Ϣ

¶¤¶¤Ó¦Óÿª·¢-Python²Ù×÷¶¤¶¤Îĵµ£¨excel°æ£©

2.3��Ȩ�����룬��ȡ��дȨ��

¶¤¶¤Ó¦Óÿª·¢-Python²Ù×÷¶¤¶¤Îĵµ£¨excel°æ£©

¶¤¶¤Ó¦Óÿª·¢-Python²Ù×÷¶¤¶¤Îĵµ£¨excel°æ£©

������������Ȩ��

¶¤¶¤Ó¦Óÿª·¢-Python²Ù×÷¶¤¶¤Îĵµ£¨excel°æ£©

�����ѯ�û�����Ȩ�ޣ�������治�ܸ����û�UserID��ѯ�û�UnionID����Ϣ��

¶¤¶¤Ó¦Óÿª·¢-Python²Ù×÷¶¤¶¤Îĵµ£¨excel°æ£©

2.4�������ĵ�����ȡworkbookID

���ĵ������Ͻǣ����������İ�ť���ڵ����Ŀ���ѡ���ĵ���Ϣ��

¶¤¶¤Ó¦Óÿª·¢-Python²Ù×÷¶¤¶¤Îĵµ£¨excel°æ£©

��ȡ����ID

¶¤¶¤Ó¦Óÿª·¢-Python²Ù×÷¶¤¶¤Îĵµ£¨excel°æ£©

2.5����ȡ�����ߵ�UserID

���롾����������̨�� ��Ա���� (dingtalk.com)

¶¤¶¤Ó¦Óÿª·¢-Python²Ù×÷¶¤¶¤Îĵµ£¨excel°æ£©

����ϸ��Ϣ�У������Ա��UserID������Ҫ����Ϣ��

¶¤¶¤Ó¦Óÿª·¢-Python²Ù×÷¶¤¶¤Îĵµ£¨excel°æ£©

2.6����ȡAccessToken

��ȡAcess Token API: API Explorer (dingtalk.com)

¶¤¶¤Ó¦Óÿª·¢-Python²Ù×÷¶¤¶¤Îĵµ£¨excel°æ£©

����ǰ���ȡ����appKey��appSecret��Ϣ����ΪAPI����Σ����ú󷵻ص�accessToken������Ҫ��token����Ч��7200�롣

2.7����ȡ�����ߵ�UnionID

����UserID,��ȡ�����ߵ�UnionID(OperatorID)��

����UserID��ȡUnionID�Ķ���API�ӿڣ� API Explorer (dingtalk.com)

��ǰ���ȡ����AccessToken��UserID��Ϣ��Ϊ��δ��룬��ȡ�û�UnionID��

¶¤¶¤Ó¦Óÿª·¢-Python²Ù×÷¶¤¶¤Îĵµ£¨excel°æ£©

2.8�����л�����Ϣ

  • AppID
  • AgentID
  • ClientID��ԭAppKey��SuiteKey��
  • ClientSecret��ԭAppSecret��SuiteSecret��
  • WorkBookID
  • UserID
  • UnionID(Ô­OperatorID)
  • AccessToken

���API����ҳ�棺

API Explorer (dingtalk.com)

��ȡAcess Token

API Explorer (dingtalk.com)

��ȡUserID:

��Ա���� (dingtalk.com)

����UserID��ѯunionid

API Explorer (dingtalk.com)

�������ɴ���demo

3.1����װpythonģ��

pip install alibabacloud_dingtalk

3.2������ͨ��ģ�����

���ݹٷ��ṩ��Demo�����ղ�ͬ���ܵ������Լ��Ĵ��롣

����ṹ���£�

  • confĿ¼��settings.py�������ļ���������־,ϵͳ�����ȣ�
  • dataĿ¼��token.json�ǻ���token�����
  • utilsĿ¼����ͨ�ù���ģ��
    • conndb.py���������ݿ��ģ�顣
    • decrypt.py�Ǽ��ܽ���ģ�顣
    • pyding_workbook.py�ǵ��ö����ĵ�API�ӿ�,���������ĵ���ģ�顣
    • AYOGIĿ¼�£�������rpt_luckbean_daily.py����ҵ����صĴ��롣

¶¤¶¤Ó¦Óÿª·¢-Python²Ù×÷¶¤¶¤Îĵµ£¨excel°æ£©

  • ����·���� ./utils/pyding_workbook.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @CreateDate   : 2024/6/7 ����10:41
# @Author       : DBArtist
# @Email        : [email protected]
# @Project      : my-python-scripts
# @ScriptFile   : pyding_workbook.py
# @Describe     :

# pip install alibabacloud_dingtalk
import os
import sys
import json
from datetime import datetime,timedelta
from typing import List
from alibabacloud_dingtalk.doc_1_0.client import Client as dingtalkdoc_1_0Client
from alibabacloud_dingtalk.doc_1_0 import models as dingtalkdoc__1__0_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_tea_util.client import Client as UtilClient
from alibabacloud_dingtalk.oauth2_1_0.client import Client as dingtalkoauth2_1_0Client
from alibabacloud_dingtalk.oauth2_1_0 import models as dingtalkoauth_2__1__0_models
from conf.settings import *

class MyWorkbook():
    def __init__(self,access_token,workbook_id=WORKBOOK_ID,operator_id=OPERATOR_ID):
        self.access_token = access_token
        self.workbook_id = workbook_id
        self.operator_id = operator_id
        self.client = self.create_client()

    @staticmethod
    def create_client() -> dingtalkdoc_1_0Client:
        """
        ʹ�� Token ��ʼ���˺�Client
        @return: Client
        @throws Exception
        """
        config = open_api_models.Config()
        config.protocol = 'https'
        config.region_id = 'central'
        return dingtalkdoc_1_0Client(config)

    def get_all_sheets(self):
        """
        ��ȡ���е�sheets
        :return:
        """
        get_all_sheets_headers = dingtalkdoc__1__0_models.GetAllSheetsHeaders()
        get_all_sheets_headers.x_acs_dingtalk_access_token = self.access_token
        get_all_sheets_request = dingtalkdoc__1__0_models.GetAllSheetsRequest(
            operator_id=self.operator_id
        )
        try:
            ret = self.client.get_all_sheets_with_options(self.workbook_id, get_all_sheets_request, get_all_sheets_headers, util_models.RuntimeOptions())
            wb_sheets_list = ret.body.value
            wb_sheets_list_format = []
            for wb_sheet in wb_sheets_list:
                wb_sheets_list_format.append([wb_sheet.id, wb_sheet.name])

            return wb_sheets_list_format
        except Exception as err:
            if not UtilClient.empty(err.code) and not UtilClient.empty(err.message):
                # err �к��� code �� message ���ԣ��ɰ���������λ����
                ERROR_LOGGER.error(f'[pyding_workbook] get_all_sheets err: {err =}')
                pass

    def check_sheet_exist(self, sheet_name):
        """
        ���ij��sheet_name�Ƿ����
        :param sheet_name:
        :return:
        """
        all_sheets_list = self.get_all_sheets()
        for wb_sheet in all_sheets_list:
            if sheet_name in wb_sheet:
                return True
        return False

    def create_sheet(self,sheet_name):
        """
        ����sheet
        :param sheet_name:
        :return:
        """
        if self.check_sheet_exist(sheet_name):
            LOGGER.info(f'[pyding_workbook] create sheet fail, {sheet_name} is already exist.')
            return None

        create_sheet_headers = dingtalkdoc__1__0_models.CreateSheetHeaders()
        create_sheet_headers.x_acs_dingtalk_access_token = self.access_token
        create_sheet_request = dingtalkdoc__1__0_models.CreateSheetRequest(
                operator_id=self.operator_id,
                name=sheet_name
            )
        try:
            sheet_obj = self.client.create_sheet_with_options(self.workbook_id, create_sheet_request, create_sheet_headers, util_models.RuntimeOptions())

            return sheet_obj
        except Exception as err:
            if not UtilClient.empty(err.code) and not UtilClient.empty(err.message):
                # err �к��� code �� message ���ԣ��ɰ���������λ����
                ERROR_LOGGER.error(f'[pyding_workbook] create_sheet err: {err =}')
                pass

    def get_sheetid_by_name(self,sheet_name):
        """
        ����sheet���Ʋ��Ҷ�Ӧ��sheet_id
        :param sheet_name:
        :return:
        """
        all_sheets = self.get_all_sheets()
        for wb_sheet in all_sheets:
            if sheet_name in wb_sheet[1]:
                return wb_sheet[0]
        return False

    def get_sheet(self,sheet_id=None, sheet_name=None):
        """
        ��ȡsheet
        :return:
        :param self:
        :return:
        """
        if sheet_id is None and sheet_name is None:
            LOGGER.info(f'[pyding_workbook] get sheet fail, sheet_id or sheet_name must atleast be specified.')
            return None
        if sheet_id is None and sheet_name is not None:
            sheet_id = self.get_sheetid_by_name(sheet_name)
            if not sheet_id:
                LOGGER.info(f'[pyding_workbook] get sheet fail, sheet_name:"{sheet_name}" is not exist.')
                return None

        get_sheet_headers = dingtalkdoc__1__0_models.GetSheetHeaders()
        get_sheet_headers.x_acs_dingtalk_access_token = self.access_token
        get_sheet_request = dingtalkdoc__1__0_models.GetSheetRequest(
            operator_id=self.operator_id
        )

        try:
            sheet_obj = self.client.get_sheet_with_options(self.workbook_id, sheet_id,
                        get_sheet_request, get_sheet_headers, util_models.RuntimeOptions())

            return sheet_obj
        except Exception as err:
            if not UtilClient.empty(err.code) and not UtilClient.empty(err.message):
                # err �к��� code �� message ���ԣ��ɰ���������λ����
                ERROR_LOGGER.error(f'[pyding_workbook] get_sheet err: {err =}')
                pass

    def delete_sheet(self,sheet_id=None,sheet_name=None):
        """
        ɾ��sheet
        :return:
        :param self:
        :return:
        """
        if sheet_id is None and sheet_name is None:
            LOGGER.info(f'[pyding_workbook] delete sheet fail, sheet_id or sheet_name must atleast be specified.')
            return None
        if sheet_id is None and sheet_name is not None:
            sheet_id = self.get_sheetid_by_name(sheet_name)
            if not sheet_id:
                LOGGER.info(f'[pyding_workbook] delete sheet fail, sheet_name:"{sheet_name}" is not exist.')
                return None

        delete_sheet_headers = dingtalkdoc__1__0_models.DeleteSheetHeaders()
        delete_sheet_headers.x_acs_dingtalk_access_token = self.access_token
        delete_sheet_request = dingtalkdoc__1__0_models.DeleteSheetRequest(
            operator_id=self.operator_id,
        )
        try:
            ret = self.client.delete_sheet_with_options(self.workbook_id, sheet_id, delete_sheet_request, delete_sheet_headers,
                                               util_models.RuntimeOptions())
            return ret
        except Exception as err:
            if not UtilClient.empty(err.code) and not UtilClient.empty(err.message):
                # err �к��� code �� message ���ԣ��ɰ���������λ����
                ERROR_LOGGER.error(f'[pyding_workbook] delete_sheet err: {err =}')
                pass

    def get_range(self,range_address,sheet_id=None,sheet_name=None):
        """
        ��ȡ��Ԫ����Ϣ
        :param range_address:
        :param sheet_id:
        :param sheet_name:
        :return:
        """
        if sheet_id is None and sheet_name is None:
            LOGGER.info(f'[pyding_workbook] get range fail, sheet_id or sheet_name must atleast be specified.')
            return None
        if sheet_id is None and sheet_name is not None:
            sheet_id = self.get_sheetid_by_name(sheet_name)
            if not sheet_id:
                LOGGER.info(f'[pyding_workbook] get range fail, sheet_name:"{sheet_name}" is not exist.')
                return None

        get_range_headers = dingtalkdoc__1__0_models.GetRangeHeaders()
        get_range_headers.x_acs_dingtalk_access_token = self.access_token
        get_range_request = dingtalkdoc__1__0_models.GetRangeRequest(
            operator_id=self.operator_id
        )
        try:
            ret = self.client.get_range_with_options(self.workbook_id, sheet_id, range_address,
                            get_range_request, get_range_headers,util_models.RuntimeOptions())
            return ret
        except Exception as err:
            if not UtilClient.empty(err.code) and not UtilClient.empty(err.message):
                # err �к��� code �� message ���ԣ��ɰ���������λ����
                ERROR_LOGGER.error(f'[pyding_workbook] get_range err: {err =}')
                pass

    def clear_range_all(self,range_address,sheet_id=None,sheet_name=None):
        """
        ����������������ݣ��������ݣ���ʽ�ȡ�������
        :return:
        """
        if sheet_id is None and sheet_name is None:
            LOGGER.info(f'[pyding_workbook] clear range all fail, sheet_id or sheet_name must atleast be specified.')
            return None
        if sheet_id is None and sheet_name is not None:
            sheet_id = self.get_sheetid_by_name(sheet_name)
            if not sheet_id:
                LOGGER.info(f'[pyding_workbook] clear range all fail, sheet_name:"{sheet_name}" is not exist.')
                return None

        clear_headers = dingtalkdoc__1__0_models.ClearHeaders()
        clear_headers.x_acs_dingtalk_access_token = self.access_token
        clear_request = dingtalkdoc__1__0_models.ClearRequest(
            operator_id=self.operator_id
        )
        try:
            cra_obj = self.client.clear_with_options(self.workbook_id, sheet_id, range_address,
                      clear_request, clear_headers, util_models.RuntimeOptions())
            return cra_obj
        except Exception as err:
            if not UtilClient.empty(err.code) and not UtilClient.empty(err.message):
                # err �к��� code �� message ���ԣ��ɰ���������λ����
                ERROR_LOGGER.error(f'[pyding_workbook] clear_range_all err: {err =}')
                pass

    def clear_range_data(self,range_address,sheet_id=None,sheet_name=None):
        """
        �����Ԫ���������ݣ���ʽ������������
        :param range_address:
        :param sheet_id:
        :param sheet_name:
        :return:
        """
        if sheet_id is None and sheet_name is None:
            LOGGER.info(f'[pyding_workbook] clear range data fail, sheet_id or sheet_name must atleast be specified.')
            return None
        if sheet_id is None and sheet_name is not None:
            sheet_id = self.get_sheetid_by_name(sheet_name)
            if not sheet_id:
                LOGGER.info(f'[pyding_workbook] clear range data faile, sheet_name:"{sheet_name}" is not exist.')
                return None

        clear_data_headers = dingtalkdoc__1__0_models.ClearDataHeaders()
        clear_data_headers.x_acs_dingtalk_access_token = self.access_token
        clear_data_request = dingtalkdoc__1__0_models.ClearDataRequest(
            operator_id=self.operator_id
        )
        try:
            crd_obj = self.client.clear_data_with_options(self.workbook_id, sheet_id, range_address,
                       clear_data_request, clear_data_headers,util_models.RuntimeOptions())
            return crd_obj
        except Exception as err:
            if not UtilClient.empty(err.code) and not UtilClient.empty(err.message):
                # err �к��� code �� message ���ԣ��ɰ���������λ����
                ERROR_LOGGER.error(f'[pyding_workbook] clear_range_data err: {err =}')
                pass

    def update_range(self,range_address,range_values,sheet_id=None,sheet_name=None,**kwargs):
        """
        ���µ�Ԫ����Ϣ��������Ԫ���е�ֵ������ɫ�������ӵȡ�
        :param range_address:
        :param sheet_id:
        :param sheet_name:
        :return:
        """
        if sheet_id is None and sheet_name is None:
            LOGGER.info(f'[pyding_workbook] update range fail, sheet_id or sheet_name must atleast be specified.')
            return None
        if sheet_id is None and sheet_name is not None:
            sheet_id = self.get_sheetid_by_name(sheet_name)
            if not sheet_id:
                LOGGER.info(f'[pyding_workbook] update range fail, sheet_name:"{sheet_name}" is not exist.')
                return None

        update_range_headers = dingtalkdoc__1__0_models.UpdateRangeHeaders()
        update_range_headers.x_acs_dingtalk_access_token = self.access_token
        update_range_request = dingtalkdoc__1__0_models.UpdateRangeRequest(
            operator_id=self.operator_id,
            values=range_values,
            **kwargs
        )
        try:
            # print(self.workbook_id, sheet_id, range_address,update_range_request, update_range_headers)
            upt_ret = self.client.update_range_with_options(self.workbook_id, sheet_id, range_address,
                        update_range_request, update_range_headers, util_models.RuntimeOptions())

            return upt_ret
        except Exception as err:
            if not UtilClient.empty(err.code) and not UtilClient.empty(err.message):
                # err �к��� code �� message ���ԣ��ɰ���������λ����
                ERROR_LOGGER.error(f'[pyding_workbook] update_range err: {err =}')
                pass


class MyToken:
    def __init__(self):
        pass

    @staticmethod
    def create_client() -> dingtalkoauth2_1_0Client:
        """
        ʹ�� Token ��ʼ���˺�Client
        @return: Client
        @throws Exception
        """
        config = open_api_models.Config()
        config.protocol = 'https'
        config.region_id = 'central'
        return dingtalkoauth2_1_0Client(config)

    @staticmethod
    def create_token(app_key=APP_KEY,app_secret=APP_SECRET) -> None:
        """
        ����token
        :param app_key:
        :param app_secret:
        :return:
        """
        client = MyToken.create_client()
        get_access_token_request = dingtalkoauth_2__1__0_models.GetAccessTokenRequest(
            app_key=app_key,
            app_secret=app_secret
        )
        try:
            ret_token_obj = client.get_access_token(get_access_token_request)
            return ret_token_obj
        except Exception as err:
            if not UtilClient.empty(err.code) and not UtilClient.empty(err.message):
                # err �к��� code �� message ���ԣ��ɰ���������λ����
                ERROR_LOGGER.error(f'[pyding_workbook] create_token err: {__qualname__} {err=}')
                pass

    @staticmethod
    def get_token(file_path,flush=False):
        """
        ��ȡtoken
        1���ȴӱ����ļ���ȡ�����û�б����ļ�����ִ�д���token����ȡ���洢�ڱ��ء�
        2����������ļ���ȡ�����ݣ����ж��Ƿ���ڣ�������ڣ���ִ�д���token,��ȡ���洢�ڱ��ء�
        3����������ļ���ȡ�����ݣ�û�й��ڣ���ֱ�ӷ��ر����ļ��д洢��token��Ϣ
        :param save_path:
        :return:
        """

        ## �����ļ������ڻ�����Ҫǿ��ˢ�£����ȡ�ٴ洢������
        if not os.path.isfile(file_path) or flush:
            LOGGER.info(f"[pyding_workbook] {file_path} is not exists, begin to create new token file.")
            # ������ȡtoken : 76eb8496841b3155850e126ad13a8a46
            token_obj = MyToken.create_token(app_key=APP_KEY,app_secret=APP_SECRET)
            access_token = token_obj.body.access_token
            expire_in = token_obj.body.expire_in
            expire_at = datetime.now() + timedelta(seconds=expire_in)
            expire_at_str = expire_at.isoformat()

            tokenData = {
                'access_token': access_token,
                'expire_in': expire_in,
                'expire_at': expire_at_str
            }

            MyToken.save_token(file_path,tokenData)
            return access_token

        # �����ļ����ڣ����ȡ����json�ļ�
        data = MyToken.read_token(file_path)
        access_token_local=data['access_token']
        expire_at_str_local=data['expire_at']
        expire_at_local = datetime.fromisoformat(expire_at_str_local)

        if expire_at_local < datetime.now():
            # ������ȡtoken : 76eb8496841b3155850e126ad13a8a46
            token_obj = MyToken.create_token(app_key=APP_KEY,app_secret=APP_SECRET)
            access_token_new = token_obj.body.access_token
            expire_in_new = token_obj.body.expire_in
            expire_at_new = datetime.now() + timedelta(seconds=expire_in_new)
            expire_at_new_str = expire_at_new.isoformat()

            tokenData = {
                'access_token': access_token_new,
                'expire_in': expire_in_new,
                'expire_at': expire_at_new_str
            }

            MyToken.save_token(file_path,tokenData)
            LOGGER.info(f"[pyding_workbook] Token expired, regenerate.")
            return access_token_new
        else:
            return access_token_local

    @staticmethod
    def save_token(file_path,token_data):
        # ���ֵ�����д�뵽JSON�ļ���
        with open(file_path, 'w', encoding='utf-8') as file:
            # ʹ��json.dump()д�����ݣ�indent�������������������ʾ�����Ŀո���
            json.dump(token_data, file, indent=4, ensure_ascii=False)
        LOGGER.info(f"[pyding_workbook] Token data save to {file_path}")
        return token_data['access_token']

    @staticmethod
    def read_token(file_path):
        with open(file_path, 'r', encoding='utf-8') as file:
            data = json.load(file)
        LOGGER.info(f"[pyding_workbook] Token data read from {file_path}")
        return data

def create_range_address(row_len, col_len, start_row=2,start_col="A"):
    """
    ���ݸ��ݴ������ʼֵ���������У���������ȡ��Ԫ������
    ����: ��A2��ʼ��3��4�е����ݣ���Ԫ��������A2:D4
    :param row_len:
    :param col_len:
    :param start_row:
    :param start_col:
    :return:
    """
    if row_len <= 0 or col_len <= 0:
        return None

    if not isinstance(start_col, str) or not (1 <= len(start_col) <= 2) or not start_col.isalpha() or not start_col.isupper():
        raise ValueError("��ʼ����������1��2λ��д��ĸ��")

    if start_row < 2:
        raise ValueError("��ʼ���������Ǵ�Լ����2��")

    end_col = get_end_column_name(start_col,col_len - 1)
    end_row = start_row + row_len - 1

    range_address = f"{start_col}{start_row}:{end_col}{end_row}"
    return range_address

def get_end_column_name(start_col, num_cols):
    """
    # ������ת��Ϊ���֣�ÿ����ĸ��Ӧ26���ݴΡ�
    # �������루A��3������ʾ��A�п�ʼ����3�У������о���C��
    :param start_col:
    :param num_cols:
    :return:
    """
    def col_to_num(col):
        return sum((26 ** i) * (ord(char) - ord('A') + 1) for i, char in enumerate(reversed(col)))

    # ������ת��������
    def num_to_col(num):
        col_name = ''
        while num > 0:
            num, rem = divmod(num - 1, 26)
            col_name = chr(rem + ord('A')) + col_name
        return col_name

    # ������ʼ�е����ֱ�ʾ
    start_num = col_to_num(start_col)

    # ��������е����ֱ�ʾ
    end_num = start_num + num_cols

    # �������е����ֱ�ʾת��������
    return num_to_col(end_num)


def get_last_column_name(total_columns, start_column='A'):
    """
    ���ݴ��������������ʼ��������ȡ���һ�е�������
    ���磺����2�����һ��������B;
         ����12�����һ��������L;
    Ĭ�϶��Ǵ�A�п�ʼ���㡣
    :param total_columns:  ������
    :param start_column:  ��ʼ�����������
    :return:
    """
    if total_columns < 1:
        raise ValueError("Invalid column number")

    def column_index(column_name):
        """Convert a column name to a 1-based index."""
        if isinstance(column_name, str):
            result = 0
            for i, char in enumerate(reversed(column_name.upper())):
                result += (ord(char) - 64) * (26 ** i)
            return result
        elif isinstance(column_name, int) and 1 <= column_name <= 702:
            # Excel columns can go up to 'XFD'
            # Excel 2007 ���Ժ�汾֧�ֵ����������16,384 �У�
            return column_name
        else:
            raise ValueError("start_column must be a column letter (A-XFD) or a positive integer between 1 and 702")

    start_index = column_index(start_column)
    adjusted_columns = total_columns + start_index - 1  # ���������ʼ�е���������

    column_name = ""
    while adjusted_columns > 0:
        adjusted_columns -= 1  # ת��Ϊ��0��ʼ������
        remainder = adjusted_columns % 26
        column_name = chr(65 + remainder) + column_name
        adjusted_columns //= 26

    return column_name


if __name__ == '__main__':
    pass
    # ## 1: ��ȡaccess_token
    # access_token = MyToken.get_token('./data/token.json')
    # # print(f'{access_token =}')
    #
    # ## ����ʵ������
    # mysample = MyWorkbook(access_token,WORKBOOK_ID,OPERATOR_ID)
    #
    # ## 2: ��ȡ����sheets�б�
    # all_sheets = mysample.get_all_sheets()
    # print(f'{all_sheets = }')
    #
    # # for wb_sheet in all_sheets:
    # #     wb_sheet_id = wb_sheet[0]
    # #     wb_sheet_name = wb_sheet[1]
    # #     print(f'[{wb_sheet_id =} ,{wb_sheet_name=}]')
    # #
    # #     ## 3: ɾ��ÿ��sheets(���뱣������һ��sheet������ȫ����ɾ����)
    # #     mysample.delete_sheet(wb_sheet_id)
    #
    # # 3: �´���sheet
    # sheet_name = 'new_sheet2'
    # cs_obj = mysample.create_sheet(sheet_name)
    # if not cs_obj:
    #     print('create sheet fail.')
    # else:
    #     print(f'{cs_obj.body.id =},{cs_obj.body.name =},{cs_obj.body.visibility =}')
    #
    # # 4: ɾ��ָ��sheet
    # ds_obj = mysample.delete_sheet(None, 'new_sheet2')
    # if not ds_obj:
    #     print('delete sheet fail.')
    # else:
    #     print(f'delete sheet status: {ds_obj.body}')
    #
    # # 5: ��ѯָ��sheet
    # gs_obj = mysample.get_sheet(None,'new_sheet1')
    # if not gs_obj:
    #     print('get sheet fail.')
    # else:
    #     print(f'get sheet msg: {gs_obj.body}')
    #
    #
    # # 6: ��ѯ��������
    # ret = mysample.get_range("A1:B3", None,'new_sheet1')
    # if not ret:
    #     print('get range fail.')
    # else:
    #     # print(f'{ret.body}')
    #     print(f'{ret.body.values}')
    #     # print(f'{ret.body.background_colors}')
    #     # print(f'{ret.body.display_values}')
    #     # print(f'{ret.body.font_sizes}')
    #     # print(f'{ret.body.font_weights}')
    #     # print(f'{ret.body.formulas}')
    #     # print(f'{ret.body.horizontal_alignments}')
    #     # print(f'{ret.body.vertical_alignments}')
    #
    # # 7: �����������������
    # range_address = "A2:B3"
    # sheet_id = None
    # sheet_name = 'new_sheet1'
    # ret = mysample.clear_range_data(range_address,sheet_id,sheet_name)
    # if not ret:
    #     print(f'clear range data fail.')
    # else:
    #     print(f'clear range data success: {ret}')
    #
    # # 8: �����������������+��ʽ
    # range_address = "A2:B3"
    # sheet_id = None
    # sheet_name = 'new_sheet1'
    # ret = mysample.clear_range_all(range_address,sheet_id,sheet_name)
    # if not ret:
    #     print(f'clear range all fail.')
    # else:
    #     print(f'clear range all success: {ret}')
    #
    #
    # # 9: ���µ�Ԫ������
    # range_address = "A1:B3"
    # range_values = [["1.21", "3.31"], ["3.43", "4.54"], ["5.65", "6.02"]]
    # sheet_id = None
    # sheet_name = 'new_sheet1'
    # ret = mysample.update_range(range_address, range_values, sheet_id, sheet_name,number_format="#,##0.00")
    # if not ret:
    #     print(f'update range fail.')
    # else:
    #     print(f'update range success: {ret.body.a_1notation}')
    #
    # # 10: �ٴβ�ѯ��������
    # ret = mysample.get_range(range_address,sheet_id, sheet_name)
    # if not ret:
    #     print('get range fail.')
    # else:
    #     # print(f'{ret.body}')
    #     print(f'get range success: {ret.body.values}')

˵����pyding_workbook.py���ǵ��ö���API�Ľӿں��Ĵ��롣
��������͸���ҵ��������API�ӿڼ��ɡ�

settings.py�ļ���Ҫ���ñ�����

APP_KEY = "xxx"
APP_SECRET = "xxx"
WORKBOOK_ID = "xxx"
OPERATOR_ID = "xxx"  ## unionid

token.json��ʽ����

{
    "access_token": "xxx",
    "expire_in": 7200,
    "expire_at": "2024-07-04T16:40:25.944534"
}

���ָ�ʽ��

���� ���ָ�ʽ ʾ��
���� "General"
�ı� "@"
���� "#,##0" 1,234
���֣�С���㣩 "#,##0.00" 1,234.56
�ٷ��� "0%" 12%
�ٷ�����С���㣩 "0.00%" 12.34%
��ѧ���� "0.00E+00" 1.01E+03
����� "?#,##0" ?1,234
����ң�С���㣩 ?#,##0.00" ?1,234.56
��Ԫ "$#,##0" $1,234
��Ԫ��С���㣩 "$#,##0.00" $1,234.56
���� "yyyy/m/d" 2022/1/1
���ڣ����ģ� "yyyy��m��d��" 2022��1��1��
���ڣ��������£� "yyyy��m��" 2022��1��
ʱ�� "hh:mm:ss" 00:00:00
����ʱ�� "yyyy/m/d hh:mm:ss" 2022/1/1 00:00:00

��Ԫ���ֵ������Range��ַ��Χ���Σ���ʽΪ��ά���顣

������ο�����ʾ����

Range��ַ��Χ�м��У��ò�����ά�����ھ��м���Ԫ�أ�Range��ַ��Χ���м��У��ò�����ά����ÿ��Ԫ���ھ��м���ֵ��

ʾ��1 ��Range��ַΪA1:B3����Χ����һ���������еı��񣬸ò���ֵ��ʽ���£� { "values": [ ["1", "2"], ["3", "4"], ["5", "6"] ] } ʾ��2 ��Range��ַΪA1:C3����Χ����һ���������еı��񣬸ò���ֵ��ʽ���£� { "values": [ ["1","2","3"], ["4","5","6"], ["7","8","9"] ] }

����ɫ����ɫ��16����ֵ������Range��ַ��Χ���Σ���ʽΪ��ά���顣������ο�����ʾ����

Range��ַ��Χ�м��У��ò�����ά�����ھ��м���Ԫ�أ�Range��ַ��Χ���м��У��ò�����ά����ÿ��Ԫ���ھ��м���ֵ��

ʾ��1 ��Range��ַΪA1:B3����Χ����һ���������еı��񣬸ò���ֵ��ʽ���£� { "backgroundColors": [ ["#ff0000", "#00ff00"], ["#f0f0f0", "#0000ff"], ["#f0f0f0", "#0000ff"] ] }

ʾ��2 ��Range��ַΪA1:C3����Χ����һ���������еı��񣬸ò���ֵ��ʽ���£� { "backgroundColors": [ ["#ff0000","#ff0000","#ff0000"], ["#ff0000","#ff0000","#ff0000"], ["#ff0000","#ff0000","#ff0000"] ] }

�����ӣ�����Range��ַ��Χ���Σ���ʽΪ��ά���顣������ο�����ʾ����

Range��ַ��Χ�м��У��ò�����ά�����ھ��м���Ԫ�أ�

Range��ַ��Χ���м��У��ò�����ά����ÿ��Ԫ���ھ��м���ֵ��

ʾ��1 ��Range��ַΪA1:B3����Χ����һ���������еı��񣬸ò���ֵ��ʽ���£�

{ "hyperlinks": [ [ { "type": "path", "link": "https://www.dingtalk.com", "text": "test" }, { "type": "sheet", "link": "Sheet2", "text": "����" } ], [ { "type": "range", "link": "Sheet2!A4", "text": "test" }, { "type": "path", "link": "https://www.dingtalk.com", "text": "����" } ], [ { "type": "range", "link": "Sheet2!A4", "text": "2" }, { "type": "sheet", "link": "Sheet2", "text": "����" } ] ] }

ʾ��2 ��Range��ַΪA1:C3����Χ����һ���������еı��񣬸ò���ֵ��ʽ���£�

{ "hyperlinks": [ [ { "type": "path", "link": "https://www.dingtalk.com", "text": "test" }, { "type": "sheet", "link": "Sheet2", "text": "����" },{ "type": "path", "link": "https://www.dingtalk.com", "text": "test" } ], [ { "type": "range", "link": "Sheet2!A4", "text": "test" }, { "type": "path", "link": "https://www.dingtalk.com", "text": "����" },{ "type": "path", "link": "https://www.dingtalk.com", "text": "test" } ], [ { "type": "range", "link": "Sheet2!A4", "text": "2" }, { "type": "sheet", "link": "Sheet2", "text": "����" },{ "type": "path", "link": "https://www.dingtalk.com", "text": "test" } ] ] }

������������ʽ

���µ�Ԫ������ - ��������ƽ̨ (dingtalk.com)
�����Ԫ���������������� - ��������ƽ̨ (dingtalk.com)

С���Ƽ��Ķ�

�������������Ľ�Ϊ������Ϣ����������������ͬ���޹۵��֤ʵ��������

�����Ƶ����

����

ͬ������

����

ɨ��ά�����������ֻ��汾��

ɨ��ά����������΢�Ź��ںţ�

��վ�������������������ϴ��������ַ���İ�Ȩ���뷢�ʼ�[email protected]

��ICP��2022002427��-10 �湫��������43070202000427��© 2013~2025 haote.com ������