I am creating pivot table in xlsx using poi and java.Here i have some questions,Please let me know if you guys know any solutions.
My Code is below
XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sheet = (XSSFSheet) wb.createSheet();
XSSFPivotTable pivotTable = sheet.createPivotTable(new AreaReference("A1:E4"), new CellReference("H5"));
pivotTable.addRowLabel(0);
pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 1);
Manually , we can create pivot the data in xlsx.But using poi, I feel some difficulties.
To add Fields in "Page Fields", addReportFilter can be used.
To add Fields in "Row Fileds", addRowLabel can be used
To add Fileds in "Data Fields", addColumnLabel can be used
To add Fields in "Column Fields", Which method can we use? Is there any option ?
And there is a method, "addDataColumn". I can't understand the purpose of this method.While trying it,i didn't get anything.
Please help me...
Related
The problem:
I have an SSIS package that loops through 100+ Excel files and reads the data, then copies the contents over to a SQL Server Table. In these Excel files, this one column has hyperlinks. The column text itself says something like DSH-LN-4, but clicking on it in Excel opens up a folder that contains some images. How do I copy the underlying link in this column rather than the actual text in the cells?
What have I tried so far:
I haven't really tried anything because I found absolutely no resources on how to do this in SSIS. Manually adding a column to the Excel files is NOT possible, since there are 100's of files. The only resource I found was in this SO Question, but this does not indicate the process of doing this without manually manipulating the Excel files.
What I would like:
In my ForEach loop container, I have a data flow task that gets the Excel contents and shoves it into the SQL Table. The column that contains hyperlinks is called PhotoReference (since these hyperlinks open the folder that has the photos). I would like this PhotoReference column to copy over the underlying hyperlink of the cell and add that to the SQL column.
For instance, I want the PhotoReference column to contain this:
www.companyname.box.com/asjdfbgkjb134kjbsdafo2bm21n4bk
If I can manage to do this, my Power BI report running off of this underlying data could contain a clickable text that would open the image directly.
Any help would be appreciated.
UPDATE:
I was able to try two different methods to extract the hyperlinks from my column, but each of these have their own issues:
Method 1: I added a Script Task component to my ForEach container and as I loop through each Excel file, used Microsoft.Office.Interop.Excel.Hyperlinks assembly to get the hyperlink from my Excel column. BUT, I don't know what to do with it after. I figured the only thing to do is to overwrite the Excel columns' content with my extracted hyperlink, but I really rather not change my Excel files in any manner.
Method 2: I added a Script Component object inside my data flow task in between my Excel source and SQL Destination. In this method, I could not get nearly as far because the Input0_ProcessInputRow method that is auto-generated has the argument Row of type Input0Buffer. I am not able to apply any Microsoft.Office.Interop.Excel properties to my Input0Buffer object. So I am stuck.
If you have to right to alter the excel files, you can simply add a Script Task before the data flow task to replace the URL column value with the hyperlink.
In this answer, I will provide a step-by-step solution to solve this problem:
Creating Excel samples
First of all, I created some Excel files with the following columns:
First name (text)
Last name (text)
Age (number)
Photo (hyperlink)
The file content looks like the following:
Creating the SSIS package
First of all, You must add an Excel connection manager that link to one of the Excel files you need to import. And an OLE DB connection manager to connect to the SQL Server instance.
You must add a SSIS variable of type string, to store the Excel file path when using the foreach enumerator
Add a Foreach loop container and configure it to loop over the Excel files as mentioned in the images below:
Within the Foreach Loop container add a Script Task and a Data flow task as mentioned in the image below:
Now, Open the data flow task and add an Excel source and an OLE DB destination and configure the columns mapping between them.
Open the Script Task configuration, and select the ExcelFilePath variable (created in step 2) as a readonly variable as mentioned in the image below:
Now, open the Script editor and in the solution explorer window, right-click on the references icon and click on "Add Reference..."
When the Add reference catalog appears, click on the COM tab, and search for Excel, then you should select the Excel Object Library from the results as shown in the following image:
Also, make sure to add Microsoft.CSharp.dll reference.
On the top of the script you should add the following line:
using Excel = Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
In the Main() function add the following lines:
Excel.Application excel = new Excel.Application();
string originalPath = Dts.Variables["User::ExcelFilePath"].Value.ToString();
Excel.Workbook workbook = excel.Workbooks.Open(originalPath);
Excel.Worksheet worksheet = (Excel.Worksheet)workbook.Worksheets[1];
Excel.Range usedRange = worksheet.UsedRange;
int intURLColidx = 0;
excel.Visible = false;
excel.DisplayAlerts = false;
for (int i = 1; i <= usedRange.Columns.Count; i++)
{
if ((worksheet.Cells[1, i] as Excel.Range).Value != null &&
(string)(worksheet.Cells[1, i] as Excel.Range).Value == "Photo")
{
intURLColidx = i;
break;
}
}
for (int i = 2; i <= usedRange.Rows.Count; i++)
{
if ((worksheet.Cells[i, intURLColidx] as Excel.Range).Hyperlinks.Count > 0)
{
(worksheet.Cells[i, intURLColidx] as Excel.Range).Value2 = (worksheet.Cells[i, intURLColidx] as Excel.Range).Hyperlinks.Item[1].Address.ToString();
}
}
workbook.Save();
Marshal.FinalReleaseComObject(worksheet);
workbook.Close(Type.Missing, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(workbook);
excel.Quit();
Marshal.FinalReleaseComObject(excel);
Dts.TaskResult = (int)ScriptResults.Success;
In the lines above, first we searched for the column index that contains the hyperlink (in this example the column name is "Photo", then we will check for each line if the Hyperlink address is not empty we will replace the column value with this hyperlink address)
Finally, make sure to configure the Excel connection manager to read the file path from the created variable value (Step 2) using expressions:
Experiments
After running the package, if we open an Excel file we will see that the Cell value is replaced with the URL:
And as shown in the image below, data are imported successfully to SQL Server:
References
Missing compiler required member 'microsoft.csharp.runtimebinder.binder.convert'
Extracting a URL from hyperlinked text in Excel cell
Excel interop prevent showing password dialog
What you will probably need to do is some hackery involving the Excel COM API, or macros. In fact, since you should stay away from using the Office COM API in SSIS.
You could pre-process excel to take that value with non-standard operations in SSIS, like using script component.
These are the steps you need to follow to import that data using the Script component:
Drag and drop a script component and select "source" as the script option type.
By default the script language is Microsoft Visual C# 2008 and I have done this sample with Microsoft Visual Basic 2008. Change this if you need to.
Define your output columns with the correct data type in "data type properties"
Edit the script. In the IDE you should add reference:
Microsoft.Excel 11.0 Object Library
(if that reference doesn´t work, try with Microsoft.Excel 5.0 Object Library)
Finally, write some code:
Imports Microsoft.Office.Interop.Excel
Public Overrides Sub getHyperlink()
Dim oExcel As Object = CreateObject("Excel.Application")
Dim FileName As String
FileName = Variables.FileName
Dim oBook As Object = oExcel.Workbooks.Open(FileName)
Dim oSheet As Object = oBook.Worksheets(1)
Output0Buffer.AddRow()
// change A1 with your correct col & row
Output0Buffer.Address = cell.range("A1").Hyperlinks(1).Address & "#" & cell.range("A1").Hyperlinks(1).SubAddress
End Sub
(keep in mind that it is a code that may not run, it is by way of illustration)
You could see code in C# here:
C# Script in SSIS Script Task to convert Excel Column in "Text" Format to "General"
The only issue with the script method is you need to have the Excel
runtime installed.
More about script component here:
https://www.tutorialgateway.org/ssis-script-component-as-transformation/
Is it possible to add a line break within an excel cell using the GemBox Spreadsheet API? For example if you're in Excel you can press Alt+Enter and go to a new line in a cell. I'm having trouble finding a property on the CellStyle class in GemBox that allows this. Is it possible?
Thanks
Yes, it is possible, for example try the following:
var ef = new ExcelFile();
var ws = ef.Worksheets.Add("Sheet1");
ws.Cells["A1"].Value = "Sample";
ws.Cells["A1"].Value += "\n" + "Sample";
ef.Save("Sample.xlsx");
In short, just use the new line character in ExcelCell.Value.
Note that when you're assigning such a value, GemBox.Spreadsheet will automatically set ExcelCell.Style.WrapText property to true.
Currently trying to add a map of users, by IP, from an SQL-Server data source. The IP's either map to a wrong location, or don't map at all using Power BI's inbuilt lookup for them.
Is there a way to query location via the IP column? Or any known API to do this for me?
Try with this: freegeoip.net
http://freegeoip.net/xml/8.8.8.8
It returns:
<Response>
<IP>8.8.8.8</IP>
<CountryCode>US</CountryCode>
<CountryName>United States</CountryName>
<RegionCode>CA</RegionCode>
<RegionName>California</RegionName>
<City>Mountain View</City>
<ZipCode>94035</ZipCode>
<TimeZone>America/Los_Angeles</TimeZone>
<Latitude>37.386</Latitude>
<Longitude>-122.0838</Longitude>
<MetroCode>807</MetroCode>
</Response>
Or using JSON:
http://freegeoip.net/json/8.8.8.8
{"ip":"8.8.8.8","country_code":"US","country_name":"United States","region_code":"CA","region_name":"California","city":"Mountain View","zip_code":"94035","time_zone":"America/Los_Angeles","latitude":37.386,"longitude":-122.0838,"metro_code":807}
I faced a similar problem, and here's what I did.
I created a New table with distinct IP addresses from the source data table.
Created a custom function which Queries the IP address and get the details for it (see at the bottom).
Clicked Add Column in the Ribbon and clicked on Invoke Custom Function
Once the query was completed, Clicked on the New Column and Expanded the table by clicking Icon on Top Right of the column.
--
The Function Code that worked for me is
= let
Source = (#"IP Address" as text) => let
Source = Json.Document(Web.Contents("http://freegeoip.net/json/" & #"IP Address")),
#"Converted to Table" = Record.ToTable(Source),
#"Transposed Table" = Table.Transpose(#"Converted to Table"),
#"Promoted Headers" = Table.PromoteHeaders(#"Transposed Table")
in
#"Promoted Headers"
in
Source
Source
I'm investigating for a client feature and I didn't reach the right answer.
This is quite simple : the user edits a full table with datas ( numbers ), chooses which cells receive the sum of which cells and export it.
In Angular we can keep the calculation and hide it to show the result. But what I would like to do is to keep the calculation active when exporting on xls.
For ex.
Cell1 = 25 Cell2 = 45
Cell3 = 70 (Sum(Cell1,Cell2));
In the XLS file It should keep the Sum() function instead of a "flat" 70.
Am I clear enough ? Does someone know a library that can do this ? or the best process to succeed in this feature ?
Excel files are essentially XML Documents.
However building Excel using plain XML is a crazy job...
You can try using the library (ClosedXML) if you are using .NET. https://closedxml.codeplex.com/
It makes much easir to build Excel files.
var wb = new XLWorkbook();
var ws = wb.AddWorksheet("Sheet1");
ws.Cell("A1").SetValue(1).CellBelow().SetValue(1);
ws.Cell("B1").SetValue(1).CellBelow().SetValue(1);
ws.Cell("C1").FormulaA1 = "\"The total value is: \" & SUM(A1:B2)";
var r = ws.Cell("C1").Value;
Assert.AreEqual("The total value is: 4", r.ToString());
// It also works if you use: ws.Cell("C1").GetString()
I've hit a problem with my database. The purpose of the section of my application is simple this; when a user marks an assignment of work complete, it will transfer one DataRow from "activeUnits" by using the "table.ImportRow" method to another table called "completedUnits" and then use the table adapter to update this change to the core database. However when testing this function the Dataset has completed the move of rows successfully internally, but upon using the TableAdapter.Update method the update of data to the database returns simply as "0" with no changes made or errors to lead.
Try
Dim activeRowMove As DataRow = Me.AssignmentDataSet.activeUnits.Rows(currentIndex)
Dim newMove As DataTable = Me.AssignmentDataSet.completedUnits
newMove.ImportRow(activeRowMove)
'UPDATE CHANGES
Me.Validate()
CompletedUnitsBindingSource.EndEdit()
Console.WriteLine(Me.CompletedUnitsTableAdapter.Update(Me.AssignmentDataSet.completedUnits))
activeUnitsTitle.Text = ("Assignment Completed!")
Catch ex As Exception
Console.WriteLine("Failed to update new table: " & ex.ToString)
activeUnitsTitle.Text = ("Failed to save!")
End Try
Is there somewhere in my code which I've simply done wrong, or any better or efficient way of moving a datarow is appreciated!
My database is not copied in my project's bin folder and every update goes to one central location.
If needed the following link is two screenshots of my current layout and data - here.
From MSDN:
Calling ImportRow preserves the existing DataRowState along with other values in the row
So, if the DataRowState in your "from" table is Unchanged, then its state will remained Unchanged in the "to" table, and it will not get saved.
Make sure to change the DataRowState of the newly imported row to Added
Cheers