Python刷新excel

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python刷新excel相关的知识,希望对你有一定的参考价值。

参考技术A 用openpyxl读取excel的load_workbook有个data_only参数。
例如:
yb_wb = load_workbook(u"D:\Desktop\xxx.xlsx", data_only=True)顾名思义,True时,只读data,忽略公式。
但是有个情景是——得先保留公式,根据旧公式写入新公式。然后再读取值进行操作。也就是说先data_only = False,然后再data_only = True。
这样会导致读取值操作的时候,公式全部没有了。对,全部为空。就是这么奇怪。

wb = openpyxl.load_workbook(‘abc.xlsx’, data_only=True)

当’abc.xlsx’被生成并在Excel程序中打开并保存之后(这个过程Excel会把公式结果计算出来),该文件附带有两套值,一套是公式全都没有计算的(data_only=False(默认)),一套是公式计算了结果的(data_only=True)。(如果没有被Excel打开并保存,则只有一套值(data_only=False的那套,公式没有计算结果的)。

此时,以data_only=True或默认data_only=False打开会得到两种不同的结果,各自独立,即data_only=True状态下打开的,会发现公式结果为None(空值)或者一个计算好的常数,而不会看到它原本的公式是如何。而data_only=False则只会显示公式而已。因此,data_only=True状态下打开,如果最后用save()函数保存了,则原xlsx文件中,公式会被替换为常数结果或空值。而data_only=False状态下打开,最后用save()函数保存了的话,原xlsx文件也会只剩下data_only=False的那套值(即公式),另一套(data_only=True)的值会丢失,如想重新获得两套值,则仍旧需要用Excel程序打开该文件并保存。

解决方法:

可以定义一个刷新函数重新打开一次并保存。

from win32com.client import Dispatch

def just_open(filename):
xlApp = Dispatch("Excel.Application")
xlApp.Visible = False
xlBook = xlApp.Workbooks.Open(filename)
xlBook.Save()
xlBook.Close()
print('自动更新结束')
filename = r"D:\Desktop\xxx.xlsx"
just_open(filename)

先调用win32com打开一次,就OK,原公式就会变成值,后面就可以愉快的操作了。

python 用于ExcelPython函数的Python装饰器。避免由Excel刷新机制导致的冗余Python函数调用。

import pandas as pd
import wrapt


def _apply_function_to_named_arg(func, arg_name):
    @wrapt.decorator
    def wrapper(wrapped, instance, args, kwargs):
        # Get argument names
        code = wrapped.__code__
        names = code.co_varnames[:code.co_argcount]

        # Convert both args and kwargs to a kwargs-style dict called all_args
        all_args = kwargs.copy()  # copy keyword args
        for n, v in zip(names, args):  # append positional args
            all_args[n] = v

        # Apply the transformation defined by `func` to the named arg
        all_args[arg_name] = func(all_args[arg_name])

        # Call the wrapped function and return its output
        return wrapped(**all_args)
    return wrapper

def negate_var(arg_name):
    return _apply_function_to_named_arg(lambda x: -x, arg_name)

@negate_var("offset")
def foo(abc, offset=1):
    return abc + offset

# Monkey-patch
pd.Series.foo = foo

# Test if it works
s = pd.Series([1, 2, 3, 4, 5])

print('Input\n-----')
print(s)
print('\nOutput of method call\n---------------------')
print(s.foo(offset=3))
print('\nOutput of function call\n-----------------------')
print(foo(s, offset=3))
## General example functions
def decorator_with_args_and_kwargs(*dec_args,**dec_kwargs):
    def wrap(f):
        print("Wrapping function...")
        def wrapped_f(*args, **kwargs):
            print("Inside wrapped function")
            print("Decorator args:", dec_args)
            print("Function args:", args)
            print("Decorator kwargs:", dec_kwargs)
            print("Function kwargs:", kwargs)
            output = f(*args,**kwargs)
            print("After f(*args,**kwargs)")
            return output
        print("Done wrapping, returning wrapped function")
        return wrapped_f
    print("Returning wrapping function")
    return wrap

def decorator_replacing_named_arg(arg_name):
    def wrap(f):
        print("Wrapping function...")
        def wrapped_f(*args, **kwargs):
            print("Inside wrapped function")
            print("Function args:", args)
            print("Function kwargs:", kwargs)

            try: # check if variable name was specified as a keyword arg
                named_arg = kwargs[arg_name]

                # Apply any transformation to the named arg
                # BEGIN
                named_arg = 0
                # END

                kwargs[arg_name] = named_arg
            except KeyError: # find the position in which the named arg is expected
                try:
                    arg_pos = f.__code__.co_varnames.index(arg_name)
                    args = list(args)  # make args mutable
                    named_arg = args[arg_pos]  # assign the named arg to a variable

                    # Apply any transformation to the named arg
                    # BEGIN
                    named_arg = 0
                    # END

                    args[arg_pos] = named_arg  # insert it back in the arg list
                    args = tuple(args)  # convert args back to a tuple
                except ValueError:
                    pass
                except IndexError:
                    pass
            output = f(*args,**kwargs)
            print("After f(*args,**kwargs)")
            return output
        print("Done wrapping, returning wrapped function")
        return wrapped_f
    print("Returning wrapping function")
    return wrap

## Specific examples
def _apply_function_to_named_arg(f, arg_name):
    # Executed when decorating the function
    # called first, when intercept(arg_names) is executed
    # returns the actual decorator which, in the second step, will receive the function as the only argument
    def decorator(func):
        # Executed when decorating the function
        # called second, this is the actual decorator

        # Try to access the arguments which were originally passed to the function which are expected
        # to be in `func._names` if `func` was already decorated
        names = getattr(func,'_names',None)
        # If `func` was not decorated before, save the input arg names in variable names
        if names is None:
            code = func.__code__
            names = code.co_varnames[:code.co_argcount]
        @wraps(func)
        def decorated(*args,**kwargs):
            # Executed on every function call
            # Convert both args and kwargs to a kwargs-style dict called all_args
            all_args = kwargs.copy()
            for n,v in zip(names,args):
                all_args[n] = v

            # Apply the transformation defined by `f` to the named arg
            all_args[arg_name] = f(all_args[arg_name])

            # Once the arguments have been overwritten, call the function
            return func(**all_args)
        decorated._names = names  # store the attributes for subsequent decorations
        return decorated
    return decorator

def negate_var(arg_name):
    return _apply_function_to_named_arg(lambda x: -x, arg_name)

@negate_var('a')
@negate_var('b')
def foo(a,b=0):
    return a+b

foo(3,2)
def noblink(func):
    def inner(*args, **kwargs):
        first_call = not(hasattr(inner, 'args')) or not(hasattr(inner, 'kwargs'))
        if not(first_call):
            new_args = not(isequal(args,inner.args) and isequal(kwargs,inner.kwargs))
        if first_call or new_args:
            #Evaluate function
            output = func(*args, **kwargs)
            # Save input arguments and output
            inner.args = args
            inner.kwargs = kwargs
            inner.output = output      
        return inner.output
    def isequal(a, b, tol=0):
        return a == b
    return inner

以上是关于Python刷新excel的主要内容,如果未能解决你的问题,请参考以下文章

用于自动刷新 Excel 电子表格的 Python 脚本

Python刷新excel

python 用于ExcelPython函数的Python装饰器。避免由Excel刷新机制导致的冗余Python函数调用。

PowerQuery在Excel中手动刷新数据连接

PowerQuery在Excel中手动刷新数据连接

使用 SSIS 脚本任务刷新 Excel