Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python使用pywin32更新MS Excel单元格范围(无循环)_Python_Excel_Pywin32 - Fatal编程技术网

Python使用pywin32更新MS Excel单元格范围(无循环)

Python使用pywin32更新MS Excel单元格范围(无循环),python,excel,pywin32,Python,Excel,Pywin32,在Python中(也是Python的新成员:-),我尝试使用pywin32操作MS-Excel文件。我正在尝试做一些目前只有pywin32可以做的事情,以及其他一些库负载可以做的事情,但理想情况下,我想用pywin32做所有事情。除了一件事(grr),我能做我需要的一切!我无法从pandas数据帧或numpy数组填充一系列单元格。我可以用VBA很好地实现这一点,示例代码如下: Dim i As Long: i = 1 Dim arr(1 To 11, 1 To 1) As Variant Dim

在Python中(也是Python的新成员:-),我尝试使用pywin32操作MS-Excel文件。我正在尝试做一些目前只有pywin32可以做的事情,以及其他一些库负载可以做的事情,但理想情况下,我想用pywin32做所有事情。除了一件事(grr),我能做我需要的一切!我无法从pandas数据帧或numpy数组填充一系列单元格。我可以用VBA很好地实现这一点,示例代码如下:

Dim i As Long: i = 1
Dim arr(1 To 11, 1 To 1) As Variant
Dim rex As Variant
    
For rex = -10 To 10 Step 2
    arr(i, 1) = rex
    i = i + 1
Next rex
ActiveSheet.Cells(1, 1).Resize(15).Value = arr
ActiveSheet.Range(Cells(1, 2), Cells(15, 2)).Value = arr
    
Dim myArray() As Variant
myArray = '[{1; 3; 4; 2; 5; 7; 6; 8; 9; 0}]'
ActiveSheet.Cells(1, 4).Resize(15).Value = myArray
ActiveSheet.Range(Cells(1, 5), Cells(15, 5)).Value = myArray
使用Python和pywin32,我可以更新一个范围,但只能获取数组中的第一个值,而不是数组中的所有值。我的Python代码的节略版本如下:

import os
import sys
import pandas as pd
import win32com.client as win32
import numpy as np
import psutil
import win32com
from win32com.client import VARIANT
import pythoncom

win32c = win32.constants
xlOpenXMLWorkbook = 51
folderOrFilePath = sys.argv[1]

# Split fullpath, filename, base filename and extension from argument
fullPath, fileName = os.path.split(folderOrFilePath)
fileNameBase, fileExtension = os.path.splitext(fileName)

# set excel object
excel = win32.gencache.EnsureDispatch('Excel.Application')
# excel can be visible or not
excel.Visible = True # Should be False for normal running / True for debugging
excel.ScreenUpdating = True # Turn off (false) for performance reasons
excel.DisplayAlerts = False
excel.EnableEvents = False

xlWb = excel.Workbooks.Open(fullFileNamePath)

ws_obj = xlWb.Sheets('sheet1')
last_row = ws_obj.UsedRange.Rows.Count
last_col = ws_obj.UsedRange.Columns.Count
ws_content_temp = ws_obj.Range(ws_obj.Cells(1, 1), ws_obj.Cells(last_row, last_col))
df1 = pd.DataFrame(ws_content_temp.Value)
dcc = df1.iloc[0].tolist()
dcc = [x.lower() for x in dcc]

df1.columns = df1.iloc[0] # Make first row the df1 column names
df1 = df1.iloc[1:] # Remove first row from the df1 as now column names

#tried defining the contents differently until I can get it working
#win32Array = ws_obj.Range(n2a(dcc.index('x')+1) + "1:" + n2a(dcc.index('x')+1) + str(lastRow)).GetValue()

#tried to populate the array manually until I can get it working
#win32Array = win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, [1, 3, 4, 2, 5, 7, 6, 8, 9, 0])
#tried to populate the array manually until I can get it working
#win32Array = VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_VARIANT,
#        [VARIANT(pythoncom.VT_UI4, 3), VARIANT(pythoncom.VT_UI4, 1), VARIANT(pythoncom.VT_UI4, 4),
#            VARIANT(pythoncom.VT_UI4, 2), VARIANT(pythoncom.VT_UI4, 5), VARIANT(pythoncom.VT_UI4, 7),
#            VARIANT(pythoncom.VT_UI4, 6), VARIANT(pythoncom.VT_UI4, 8), VARIANT(pythoncom.VT_UI4, 9),
#            VARIANT(pythoncom.VT_UI4, 0)])

#tried
#ws_obj.Cells(2, dcc.index('x')+2).Resize(df1.shape[0]).Value = df1['x'].to_numpy()
#ws_obj.Range(ws_obj.Cells(2, dcc.index('x')+2), ws_obj.Cells(df1.shape[0],dcc.index('x')+2)).Value = df1['x'].to_numpy()
#ws_obj.Cells(2, dcc.index('x')+2).Resize(df1.shape[0]).Value = win32Array
#ws_obj.Range(ws_obj.Cells(2, dcc.index('x')+2), ws_obj.Cells(df1.shape[0],dcc.index('x')+2)).Value = win32Array

xlWb.SaveAs(os.path.normpath(f'{fullPath}\\{fileNameBase}_Output.xlsx'), xlOpenXMLWorkbook)
xlWb.Close(False)
excel.ScreenUpdating = True
excel.DisplayAlerts = True
excel.EnableEvents = True
由于我能够更新范围,但无法获得数组/数据帧中的所有值在整个范围内的正确分布,因此我将搜索/尝试的重点放在了确保数组/数据帧的正确定义上,因此查看了像和这样的链接,只突出显示了两个,但到目前为止仍然没有运气


期待着您的建议。

我已经找到了答案。这个问题显然是因为我选择了一列,因此在pywin32 range对象需要二维数组时生成了一维数组。正在处理下面的节略代码

import os
import sys
import pandas as pd
import win32com.client as win32
import numpy as np
import psutil
import win32com
from win32com.client import VARIANT
import pythoncom

win32c = win32.constants
xlOpenXMLWorkbook = 51
folderOrFilePath = sys.argv[1]

# Split fullpath, filename, base filename and extension from argument
fullPath, fileName = os.path.split(folderOrFilePath)
fileNameBase, fileExtension = os.path.splitext(fileName)

# set excel object
excel = win32.gencache.EnsureDispatch('Excel.Application')
# excel can be visible or not
excel.Visible = True # Should be False for normal running / True for debugging
excel.ScreenUpdating = True # Turn off (false) for performance reasons
excel.DisplayAlerts = False
excel.EnableEvents = False

xlWb = excel.Workbooks.Open(fullFileNamePath)

ws_obj = xlWb.Sheets('sheet1')
last_row = ws_obj.UsedRange.Rows.Count
last_col = ws_obj.UsedRange.Columns.Count
ws_content_temp = ws_obj.Range(ws_obj.Cells(1, 1), ws_obj.Cells(last_row, last_col))
df1 = pd.DataFrame(ws_content_temp.Value)
dcc = df1.iloc[0].tolist()
dcc = [x.lower() for x in dcc]

df1.columns = df1.iloc[0] # Make first row the df1 column names
df1 = df1.iloc[1:] # Remove first row from the df1 as now column names

dataArray = pd.DataFrame(df1['x'].apply(pd.Series)).to_numpy() # Need to ensure not output a 1D Array as the Excel Range Object is expecting a 2D Array
ws_obj.Range(ws_obj.Cells(2, dcc.index('x')+1),ws_obj.Cells(df1.shape[0]+1,dcc.index('x')+1)).Value = dataArray

xlWb.SaveAs(os.path.normpath(f'{fullPath}\\{fileNameBase}_Output.xlsx'), xlOpenXMLWorkbook)
xlWb.Close(False)
excel.ScreenUpdating = True
excel.DisplayAlerts = True
excel.EnableEvents = True

可能值得注意的是,pywin32中的.Resize函数的工作原理与VBA中的不同。只能将其用于更新单个单元格,因此使用.Range对象方法。