Как бухгалтер, вы можете столкнуться со случаями, когда закон требует, чтобы вы разбили все бухгалтерские документы, чтобы каждая проводка по дебету соответствовала ровно одной проводке по кредиту, и наоборот.

Что делать, если ваша бухгалтерская система не поддерживает вас в этом? Разбивка большой электронной таблицы GL вручную — очень скучная и трудоемкая задача.

Сегодня я представлю метод разбивки бухгалтерских документов с помощью Python и Pandas.

Pandas – это быстрый, мощный, гибкий и простой в использовании инструмент для анализа и обработки данных с открытым исходным кодом, созданный на основе языка программирования Python. Если вы не знаете о Pandas, посетите веб-сайт:



Pandas предоставляет отличную документацию, так что вы можете быстро с ней ознакомиться. В роли бухгалтера я активно использую Pandas для автоматизации повседневных задач.

Учитывая, что у нас есть электронная таблица GL следующим образом:

Мой файл GL хранится по пути: «D:/GL.xlsx»

  1. Начнем с использования Pandas для чтения файла GL.
# Read the excel file to get a Pandas dataframe
df=pd.read_excel("D:/GL.xlsx")

Визуализация фрейма данных при просмотре с помощью Jupyter Notebook почти аналогична электронной таблице Excel.

Желаемый результат:

2. Напишите 04 функции для управления данными

# Check if there is any values different from 0 or empty
def check_dict_values(dict_):
    for i in dict_.values():
        if i!=0:
            return False
    return True
# Transform a original data frame to dictionary
# Return three values:
# debit_account_dict : Dictionary , key is account number, value is amount
# credit_account_dict : Dictionary , key is account number, value is amuont
# The returned values are inputs for find_match_outer() function

def get_dict_from_data_frame(df):
    # Create two data frames by filter 'Debit/Credit' column
    # get rows that sastify the condition that columns 'Debit/Credit' value is 'Debit'
    df_debit= df.loc[df['Debit/Credit']=='Debit'] 

    # get rows that sastify the condition that columns 'Debit/Credit' value is 'Credit'
    df_credit= df.loc[df['Debit/Credit']=='Credit']

    # Use zip() built-in function to create a zip object from two Data Frame columns
    # Use dict() built-in function to convert zip object to a Dictonary
    debit_account_dict= dict(zip(df_debit['Account_number'], df_debit['Amount']))
    credit_account_dict= dict(zip(df_credit['Account_number'], df_credit['Amount']))

    return debit_account_dict,credit_account_dict,df['Document_number'].to_list()[0]
# This function will return the transformed dataframe for each docmument number
# Parameters are output of get_dict_from_data_frame() function
def find_match_outer(debit_account_dict, credit_account_dict, document_number):
    # I use nested function since I want three below variables are in local scope only
    # These lists will be modified by the inner function
    # We will use these lists to create a dictionary 
    # We will use the dictionary to create a data frame
    debit_account_list=[]
    credit_account_list=[]
    value_list=[]

    # Inner function : 
    def find_match_inner(debit_account_dict, credit_account_dict):
        # The function will loop until debit_account_dict or check_dict_values is empty 
        while True:
            # if map values are zero or empty -> work done
            if(check_dict_values(debit_account_dict) or check_dict_values(credit_account_dict)):
                return
            # Find the key of min value of debit
            min_debit_key= min(debit_account_dict, key = lambda k: debit_account_dict[k])
            # Find min debit value
            min_debit_value= debit_account_dict[min_debit_key]
            # Find the key of min value of credit
            min_credit_key = min(credit_account_dict, key = lambda k: credit_account_dict[k])
            # Find min credit value
            min_credit_value= credit_account_dict[min_credit_key]

            # Add keys of min values to lists
            debit_account_list.append(min_debit_key)
            credit_account_list.append(min_credit_key)
            # Compare
            if(min_credit_value <= min_debit_value):
                print("min is credit: ",min_credit_value)
                value_list.append(min_credit_value)
                # Decrease value of min_debit_key in the debit_account_dict by min_credit_value
                debit_account_dict[min_debit_key]-=min_credit_value
                # Remove min_credit_key from credit_account_dict
                credit_account_dict.pop(min_credit_key)
            else:
                print("min is debit: ",min_debit_value)
                value_list.append(min_debit_value)
                # Decrease value of min_debit_key in the debit_account_dict by min_debit_value
                credit_account_dict[min_credit_key]-=min_debit_value
                 # Remove min_credit_key from credit_account_dict
                debit_account_dict.pop(min_debit_key)

    # Call inner function
    find_match_inner(debit_account_dict, credit_account_dict)
    # Create a data frame from dictionary, the dictionary is created from 03 lists that I have defined 
    df=pd.DataFrame({'Debit_account': debit_account_list, 'Credit_account': credit_account_list,'Value':value_list})
    df['Document_number']=document_number
    # Re-arrange columns position
    df= df.loc[:,['Document_number','Debit_account','Credit_account','Value']]
    return df
# This function will take the original data frame read from spread sheet as input
# Return the final result
def transform(df):
    # Define an empty list to hold transformed dataframes
    df_list_transformed=[]
    # Use df.groupby('Document_number') to get a pandas.core.groupby.generic.DataFrameGroupBy object
    # Unpack DataFrameGroupBy object and use Python list comprehension syntax to make a list of DataFrames
    df_list_org = [df for _, df in df.groupby('Document_number')]
    
    # Loop through df_list_org 
    for df in df_list_org:
        # Transfrom each data frame
        debit_account_dict, credit_account_dict, document_number=get_dict_from_data_frame(df)
        df_transformed= find_match_outer(debit_account_dict, credit_account_dict, document_number)
        # Add transformed dataframes to df_list_transformed
        df_list_transformed.append(df_transformed)
    
    # Concatenate transformed dataframes
    df_concat= pd.concat(df_list_transformed)

    # Reset index
    df_concat.reset_index(inplace=True,drop=True)
    return df_concat

3. Проверим, как работает наша программа

# Read the excel file to get a Pandas dataframe
df=pd.read_excel("D:/GL.xlsx")
# Transform data using written functions
df_transformed=transform(df)

4. Результат ожидаемый, в каждой строке мы видим дебетовый счет и соответствующий ему кредитный счет.

Спасибо за прочтение, надеюсь, что моя статья окажется для вас полезной!

Я также являюсь предпринимателем, начинающим бизнес в области вышивки. Пожалуйста, посетите мой веб-сайт, если вы заинтересованы в вышивальных изделиях: http://anhoahome.com