simple question but I can't seem to find an answer anywhere so I'll put it here: how to you assign table styles to tables, yet not map it to a default table style i.e. make custom style elements? I read it might involve .TableStyleElements but when I tried to add ActiveSheet.ListObjects("Table1").TableStyleElements(xlHeaderRow).Font.Color = RGB(119, 184, 0) it breaks. Am I getting the syntax wrong?
I believe you need to declare the table style first eg:
Dim oTblStyle As TableStyle
Set oTblStyle = ActiveSheet.ListObjects("Table1").TableStyle
oTblStyle.TableStyleElements.Item(xlHeaderRow).Font.Color = RGB(119, 184, 0)
Related
I work with Excel Interop, I try to get color of rows from specyfic Table Style.
I get name of Table Style like that:
var TableStyle = table.TableStyle.Name.ToString();
But I haven't got idea how get colors from known style.
I soloved my problem.
If somebody will have similar in the future.
You can access to table in that way:
var tse = table.TableStyle.TableStyleElements;
double rs1 = ((TableStyleElement)tse[5]).Interior.Color;
double rs2 = ((TableStyleElement)tse[6]).Interior.Color;
when indexes of tse is an enum:
https://learn.microsoft.com/en-us/dotnet/api/microsoft.office.interop.excel.xltablestyleelementtype?view=excel-pia
But If you need create new style, you should copy existing and edit.
https://learn.microsoft.com/en-us/previous-versions/office/developer/office-2010/hh273483(v=office.14)?redirectedfrom=MSDN
I have generated an Excel table using PHPSpreadsheet including the style and the autofilter:
The problem is when I sort the data by the second and third columns, the table formatting is gone. This is how it looks like compared if I use Table Style directly from Excel (using Home-> Format as Table):
Is there any way to keep the formatting when I sort the table generated from PHPSpreadsheet?
Relevant PHP Code:
for ($rowNumber = 0, $rowNumberMax = sizeof($rows); $rowNumber < $rowNumberMax; $rowNumber++) //rows (all data)
{
$columnNumber = 0; //1 = A
for ($i = 0, $j = sizeof($tableColumns); $i < $j; $i++) //loop through table header label
{
foreach ($rows[$rowNumber] as $rowKey => $rowValue) //loop through single row data
{
if($tableColumns[$i] == $rowKey)
{
$sheet->setCellValueByColumnAndRow($columnNumber + 1, ($rowNumber + 5), $rowValue);
$currentCell = Utilities::num2alpha($columnNumber) .''. ($rowNumber + 5);
$sheet->getStyle($currentCell)->getNumberFormat()->setFormatCode('#');
$sheet->getStyle($currentCell)->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_LEFT);
if(($rowNumber+5) % 2 == 0)
{
//even row
$sheet->getStyle($currentCell)->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)->getStartColor()->setARGB('ffd9e1f2');
}
else
{
//odd row
}
$columnNumber++;
break;
}
}
}
}
//set autofilter
$headerFirstCellPosition = 'A4';
$tableLastCellPosition = Utilities::num2alpha(sizeof($tableColumns) - 1) . '' . (sizeof($rows) + 4);
$sheet->setAutoFilter($headerFirstCellPosition . ':' . $tableLastCellPosition);
The problem is you were just applying formatting to the cells based on if the row was even or odd, but it wasn't actually replicating a table in Excel. You would find the same result in Excel if you just formatted every other row like you did with your PHP code, where the "table" format would get lost.
Somebody just recently implemented a first pass of the actual table feature in Excel: https://github.com/PHPOffice/PhpSpreadsheet/pull/2671
You need to be on PHPSpreadSheet version 1.23.0 in order to be able to use this.
Using that, you would have to modify your code but you can go to the Samples section in the code area and view how to implement it: https://github.com/PHPOffice/PhpSpreadsheet/tree/master/samples/Table
https://github.com/PHPOffice/PhpSpreadsheet/blob/master/samples/Table/01_Table.php
Here is the relevant code (I removed some of the lines and added additional comments from the 01_Table.php sample at the link provided).
Table styles can be found here: https://github.com/PHPOffice/PhpSpreadsheet/blob/master/src/PhpSpreadsheet/Worksheet/Table/TableStyle.php
// Create Table
$table = new Table('A1:D17', 'Sales_Data');
// Create Table Style
$tableStyle = new TableStyle();
// this line is the style type you want, you can verify this in Excel by clicking the "Format as Table" button and then hovering over the style you like to get the name
$tableStyle->setTheme(TableStyle::TABLE_STYLE_MEDIUM2);
// this gives you the alternate row color; I suggest to use either this or columnStripes as both together do not look good
$tableStyle->setShowRowStripes(true);
// similar to the alternate row color but does it for columns; I suggest to use either this or rowStripes as both together do not look good; I personally set to false and only used the rowStripes
$tableStyle->setShowColumnStripes(true);
// this will bold everything in the first column; I personally set to false
$tableStyle->setShowFirstColumn(true);
// this will bold everything in the last column; I personally set to false
$tableStyle->setShowLastColumn(true);
$table->setStyle($tableStyle);
Also make sure that you include the following to be able to use these:
use PhpOffice\PhpSpreadsheet\Worksheet\Table;
use PhpOffice\PhpSpreadsheet\Worksheet\Table\TableStyle;
Implementing that into your code will then allow you to sort using the auto filters and keep the formatting like you are expecting.
There are a few caveats such as:
Note that PreCalculateFormulas needs to be disabled when saving spreadsheets containing tables with formulae (totals or column formulae).
Also, as I am actually currently working on doing this, it doesn't look like you can apply an autofilter and have a table at the same time at this point.
That does appear to be on the todo list though, as the first link I provided the contributor has "Filter expressions similar to AutoFilter."
Otherwise, that should get you what you want and aside from being able to auto filter prior to creating the Excel file, it has worked well in my small testing.
Edit to add:
I think you can actually simplify your code a bit by using the functionality of PHPSpreadsheet to create a a spreadsheet from an array.
Documentation from PHPSpreadsheet can be found here: https://phpspreadsheet.readthedocs.io/en/latest/topics/accessing-cells/#setting-a-range-of-cells-from-an-array
You'll need to change it so that the array that is holding the info starts with your headers, so I believe that would look similar to this for your code:
$rows = [
['header1', 'header2', 'header3', 'header4']
];
Then you can populate the $rows array with your data from the rows either with a loop or just a single declaration depending on what you are putting in there, but basically using the below to populate the array.
$rows[] = [
$field1Data,
$field2Data,
$field3Data,
$field4Data
];
After you do that, you can then generate the spreadsheet using the following:
$sheet->getActiveSheet()
->fromArray(
$rows, // the data to set
NULL, // array values with this value will not be set
'A1', // top left coordinate of the worksheet range where we want to set these values (default is A1)
true // adds 0 to cell instead of blank if a 0 is the value
);
After doing the above, you can then add the code to create the table I posted and then save the file and you should be good.
Also, if you are in a situation where you still need to use the autofilter (for instance if you want to pre-filter the file on one or more columns which at this point you can't use a table when doing), you can make the autofilter call a bit easier.
// determine the the number of rows in the active sheet
$highestRow = $spreadsheet->getActiveSheet()->getHighestRow();
// get the highest column letter
$highestColumn = $spreadsheet->getActiveSheet()->getHighestColumn();
// set autofilter range
$spreadsheet->getActiveSheet()->setAutoFilter('A1:'.$highestColumn.$highestRow);
I realize the additional edit goes beyond the question, but figured I'd point it out since there are some built-in methods that you could use to reduce some of your code.
-Matt
I have word document with different styles like heading1, heading2, normal, bodytext etc. I'm trying to write a VBA macro which will first modify the styles as per requirement and then apply those styles across the document accordingly. See below, I'm changing the font size first for style=normal and heding1 and then want to apply it for all paragraphs where style=normal is already defined. So it will update the style for existing heading1 and normal separately.
NOTE: I want to do it with style only. I can do it using for loop by going each paragraph one by one and then find what is the style of that paragraph and then apply the style accordingly AND it is working perfectly if I do in this way but in my document I have 60000 paragraphs and so it is taking long time like 10 hours. So, Im looking for a way to do it for each different styles in one shot. Please let me know if there is any way to do it.
ActiveDocument.Styles(wdStyleNormal).Font.Name = "Arial"
ActiveDocument.Styles(wdStyleNormal).Font.Size = 12
ActiveDocument.Styles(wdStyleHeading1).Font.Name = "Arial"
ActiveDocument.Styles(wdStyleHeading1).Font.Size = 20
ActiveDocument.UpdateStyles
I have tried and ended up with this solution. I hope it will work for you.
Sub ChangeStyle()
With ActiveDocument.Styles("wdStyleNormal").Font
.Color = wdColorAqua 'wdColorRed
.Name = "Arial"
.Size = 12
End With
With ActiveDocument.Styles("wdStyleNormal")
.AutomaticallyUpdate = True
End With
End Sub
I'm trying to fill out template PDF with data from excel worksheet using VBA and here's what I have so far;
FILE_NAME_TEMPLATE = "path_to\template.pdf"
Set gApp = CreateObject("AcroExch.app")
Set avDoc = CreateObject("AcroExch.AVDoc")
If avDoc.Open(FILENAME, "") Then
Set pdDoc = avDoc.GetPDDoc()
Set jso = pdDoc.GetJSObject
'populating pdf fields here, no issues
FILE_NAME_RESULT = "path_to\result.pdf"
pdDoc.Save PDSaveFull, FILE_NAME_RESULT
pdDoc.Close
End If
avDoc.Close (True)
As is, code populates and saves template.pdf, however I'd like to leave template file unchanged and create the new result.pdf with populated data. Please explain what am I doing wrong and thank you for your time.
(Not enough points to just comment yet, so posting as an answer instead)
Is pdDoc.Close a Function and if so, what's its return value?
As a workaround, you could copy the template to the result file first and then work on the file.
FileCopy FILE_NAME_TEMPLATE, FILE_NAME_RESULT
Let me add a coding style best practice recommendation: use all upper-case names for constants only. For actual variables, use mixed case names (like you did with e.g. pdDoc.
I was looking for this too and it took me days: Just use the document flag (long) instead of the argument:
pdDoc.Save 1, FILE_NAME_RESULT
I have googled a while for the methods to create excel files (*.xlsx, not the csv files) using programming languages, such as C++ or PHP. here is an example, http://www.the-art-of-web.com/php/dataexport/
But Ideally, I want to be able to specify the colours for each cell. For example, in VBScript using COM object Excel.Application, the code looks like:
Set objExcel = CreateObject("Excel.Application")
objExcel.Visible = False
objExcel.DisplayAlerts = False
Set objWorkbook = objExcel.Workbooks.Add
Set objWorksheet = objWorkbook.Worksheets(1)
With objWorksheet
.Cells(1,1).Interior.Color=RGB(245,245,245)
...
...
...
End With
objWorkbook.SaveAs("sample.xlsx")
objExcel.Quit
How can I do this without the use of COM object? I need the program to work platform-independent so COM object is not a good choice.
Update: here is an interesting post, that generates the VBS file and double click the VBS file will give you a nice picture in Excel by drawing cells with different colors.
You can modify cell backgrounds using python and the XLSX Writer module. While it is not the C++ or PHP language you mentioned, Python is cross platform and the code below works on the Fedora box I tested with.
First, you need python and the module mentioned above. You can install the module by doing this:
pip install xlsxwriter
Next, we are going to modify the first tutorial to provide a little color to the "Total" value.
import xlsxwriter
# Create a workbook and add a worksheet.
workbook = xlsxwriter.Workbook('Expenses01.xlsx')
worksheet = workbook.add_worksheet()
# Some data we want to write to the worksheet.
expenses = (
['Rent', 1000],
['Gas', 100],
['Food', 300],
['Gym', 50],
)
# Start from the first cell. Rows and columns are zero indexed.
row = 0
col = 0
green_format = workbook.add_format()
green_format.set_pattern(1) # This is optional when using a solid fill.
green_format.set_bg_color('#008000')
# Iterate over the data and write it out row by row.
for item, cost in (expenses):
worksheet.write(row, col, item)
worksheet.write(row, col + 1, cost)
row += 1
# Write a total using a formula.
worksheet.write(row, 0, 'Total')
worksheet.write(row, 1, '=SUM(B1:B4)', green_format)
workbook.close()
The things that were added are these lines. This utilizes the set_bg_color function.
green_format = workbook.add_format()
green_format.set_pattern(1) # This is optional when using a solid fill.
green_format.set_bg_color('green')
And the =SUM row was modified to use this green format:
worksheet.write(row, 1, '=SUM(B1:B4)', green_format)
This code creates a green cell at B5.
A note about the color: I provided the color 'green', because that is one of the few colors that are mapped to an RGB value. If you need to use something other than these colors, you can provide an RGB value. #008000 maps to green
green_format.set_bg_color('#008000')
This line is functionally identical to the one provided above.
If you want to use PHP, there are at least two different toolkits, which will generate Excel files without the use of COM Object :
PhpExcel and ExcelWriterXML.
For ExcelWriterXML for instance, changing the background color is $format->bgColor('Black'); , see complete example on the site.
Another way is to produce xlsx files (which are XML inside) through a template engine like TinyButStrong.