Excel stored in List<Map<String,String>> - excel

I am trying to read an excel sheet and save it in Java Data Structure List> list
Basically I am having a table in the excel sheet
|Name|FirstName|emp_ID|Age|
|aaaa|bbbbbbbbb|111111|40 |
|cccc|fffffffff|222222|25 |
where the keys will be
|Name|FirstName|emp_ID|Age|
my list of map should look as bellow
{Name=aaaa, FirstName=bbbbbbbbb, emp_ID=111111, Age=40}
{Name=cccc, FirstName=fffffffff, emp_ID=222222, Age=25}
but my list is storing the second map two times
{Name=cccc, FirstName=fffffffff, emp_ID=222222, Age=25}
{Name=cccc, FirstName=fffffffff, emp_ID=222222, Age=25}
any idea how to fix the issue please or any better suggestion
Thank You in advance
Here is the code That I wrote
workbook = WorkbookFactory.create(inStream);
workSheet = workbook.getSheetAt(0);
DataFormatter df = new DataFormatter();
Map<String, String> myMap = new LinkedHashMap<>();
List<Map<String, String>> list = new ArrayList<>();
row = workSheet.getRow(0);
ArrayList<String> headersName = new ArrayList<String>();
for (int j = 0; j <= row.getPhysicalNumberOfCells(); j++) {
row.getCell(j);
if ((df.formatCellValue(row.getCell(j)).isEmpty())) {
continue;
} else {
headersName.add(df.formatCellValue(row.getCell(j)));
}
}
System.out.println(headersName);
OUTER: for (Row myrow : workSheet) {
for (int i = 0; i < myrow.getLastCellNum(); i++) {
if (myrow.getRowNum() == 0) {
continue OUTER;
}
String value = df.formatCellValue(myrow.getCell(i));
myMap.put(headersName.get(i), value);
}
list.add(myMap);
}
System.out.println(list.size());
for (Map<String, String> map : list) {
System.out.println(map);
}
the print of my list
{Name=cccc, FirstName=fffffffff, emp_ID=222222, Age=25}
{Name=cccc, FirstName=fffffffff, emp_ID=222222, Age=25}

The issue lies in myMap.put(headersName.get(i), value). In that line, if the key already exists in the map, it overrides it. But later on, list.add(myMap) passes a reference to the same map, not a new version of it. So on the second iteration, when the line overrides the value, it overrides it on the first map already in the list. See below for a basic example of the same issue.
import java.util.*;
public class Example {
public static void main(String []args) {
Map<String, String> myMap = new LinkedHashMap<>();
List<Map<String, String>> list = new ArrayList<>();
myMap.put("abc", "123");
list.add(myMap);
System.out.println(list.get(0));
myMap.put("abc", "234");
System.out.println(myMap);
System.out.println(list.get(0));
}
}
To fix it, look into deep copies so that changing one doesn't change them all.

Related

WordProcessingDocument not preserving whitespace

I'm writing a C# program using XML and Linq that reads in data from tables stored in a word document and inserts it into an excel spreadsheet. The code I have so far does this, however it does not preserve any new lines (in the word doc the "new line" is done by pressing the enter key). Using the debugger, I can see that the new lines aren't even being read in. For example, if the text I want to copy is:
Something like this
And another line
And maybe even a third line
It gets read in as:
Something like thisAnd another lineAnd maybe even a third line
I can't separate the lines by a character as the words could be anything. This is what I have so far:
internal override Dictionary<string, string> GetContent()
{
Dictionary<string, string> contents = new Dictionary<string, string>();
using (WordprocessingDocument doc = WordprocessingDocument.Open(MainForm.WordFileDialog.FileName, false))
{
List<Table> tables = doc.MainDocumentPart.Document.Descendants<Table>().ToList();
foreach (Table table in tables)
{
TableRow headerRow = table.Elements<TableRow>().ElementAt(0);
TableCell tableSectionTitle;
try
{
tableSectionTitle = headerRow.Elements<TableCell>().ElementAt(0);
}
catch (ArgumentOutOfRangeException)
{
continue;
}
List<TableRow> rows = table.Descendants<TableRow>().ToList();
foreach (TableRow row in rows)
{
TableCell headerCell = row.Elements<TableCell>().ElementAt(0);
if (headerCell.InnerText.ToLower().Contains("first item"))
{
contents.Add("first item", row.Elements<TableCell>().ElementAt(1).InnerText);
}
else if (headerCell.InnerText.ToLower().Contains("second item:"))
{
char[] split = { ':' };
Int32 count = 2;
string str = row.Elements<TableCell>().ElementAt(0).InnerText;
String[] newStr = str.Split(split, count, StringSplitOptions.None);
contents.Add("second item:", newStr[1]);
}
**continues for many more else if statements**
else
{
continue;
}
}
}
return contents;
}
}
I'm new to using XML, so any help would be appreciated!

How to group csv data by specific column name row wise using Java 7 only

Format of csv is
Row1:c1,c2,c3,c4,c5
Row2:1,a,b,c,d
Row3:1,n,b,c,l
Row4:2,j,k,c,l
Row5:3,a,i,v,i
Row6:1,a,b,c,d
Row7:1,a,b,u,i
Grouping should be done on basis of column c1,c2,c3, if all these three column values are same then group it as follows:
GROUP1: row2 and row 7 are same and map should be Map(Map(String, String),Map(String, String))
i.e. one key{c1,1},{c2,a},{c3,b} (key value pair again)
with multiple values as
{c4,c},{c5,d} (key value pair )
{c4,u},{c5,i} (key value pair )
GROUP2:Row 3 does not have same value with respect to columns so the map should be
key{c1,1}{c2,n}{c3,b}
value{c4,c}{c5,l}
Row7 should be added to error map as the row is same as row2
Final Map should be Map of(group.Num,Objects)
Column name should be picked from property file as shown below.
public class app3 {
public static void main(String args[]) throws IOException {
File CSV_FILE_PATH = new File("csv.csv");
CsvMapReader mapReader = null;
try {
mapReader = new CsvMapReader(new FileReader(CSV_FILE_PATH), CsvPreference.STANDARD_PREFERENCE);
final String[] header = mapReader.getHeader(true);
final CellProcessor[] processors = getProcessors();
Map<String, Object> customerMap;
Map<Integer,Map<String, Object>> finalMap = new HashMap<Integer,Map<String, Object>>();
while( (customerMap = mapReader.read(header, processors)) != null ) {
finalMap.put(mapReader.getLineNumber(), customerMap);
}
}
}
finally {
if( mapReader != null ) {
mapReader.close();
}
}
}
private static CellProcessor[] getProcessors() throws IOException {
InputStream input = new FileInputStream("fileAttributesconfig.properties");
Properties prop= new Properties();
prop.load(input);
CellProcessor[] processors=new CellProcessor[prop.size()];
for(int i=0; i< prop.size(); i++){
processors[i]=new Optional();
}
return processors;
}
}
The have done multiple trials but group by is supported only by 8, but specifically i need to use java 7.Could someone can help me here? I need more ideas to over come this

Variable outside local scope is not defined for test case

I wish to access outside variables for a test function that I am writing, in Groovy.
However, it doesn't seem that I can.
My code is like this:
Map<String, String> originalTableRowState = new HashMap<String, String>(),
newTableRowState
// if there is table data to get, and do actions on
def WebDriver driver = DriverFactory.getWebDriver()
def List<WebElement> dataRows = driver.findElements(
By.cssSelector('div.tab-pane.active .dataTables_scrollBody tbody tr:not(.dataTables_empty)'))
'if there\'s table data, this test should run'
if (dataRows.size() > 0) {
WebUI.comment('populate the tableRowState with the data from the first table row')
fetchFirstRowDataInto(originalTableRowState)
}
void fetchFirstRowDataInto(Map<String, String> tableRowState) {
List<WebElement> tableHeadings = driver.findElements(
By.cssSelector('div.tab-pane.active .dataTables_scrollHead th'))
WebElement firstRow = dataRows.get(0)
List<WebElement> dataCells = firstRow.findElements(
By.xpath('//td[not(#class="dataTables_empty") and not(*)]'))
for (int i = 0; i < dataCells.size(); i++) {
// save data to originalTableRowState with the table header text as the key
tableRowState.put(tableHeadings.get(i), dataCells.get(i))
}
}
and when I run it, it greets me with the error saying that Variable 'driver' is not defined outside test case. I just added the def keywords to the driver,dataRows definintions.
How to make driver,dataRows accessible inside functions, without passing them in as parameters?
I fixed the method variable-access issue by declaring it a JS-like closure:
/* change void fetchFirstRowDataInto(Map<String, String> tableRowState) { to def fetchFirstRowDataInto = { Map<String, String> tableRowState -> */
and putting the definition above the invocation.
I welcome any better solutions...

System.OutOfMemoryException: Exception of Type 'System.OutOfMemory' was thrown

private List<T> ReadCurrentFile(string currentExtractedFile, PurgingDetails purgingParams)
{
List<T> thinLogDoList = new List<T>();
using (StreamReader sr = new StreamReader(currentExtractedFile))
{
string currentLine = string.Empty;
Dictionary<string, string> ColumnNamesDictionary = null;
while ((currentLine = sr.ReadLine()) != null)
{
if (currentLine.IsNotNullOrEmpty() && currentLine.Contains("Æ"))
{
string[] columnNames = currentLine.Split(new char[] { 'Æ' });
ColumnNamesDictionary = FillColumnNameDictionary(columnNames);
if (CheckForValidConditions(ColumnNamesDictionary, purgingParams))
{
thinLogDoList.Add(FillThinLogDO(ColumnNamesDictionary));
}
}
}
}
return thinLogDoList;
}
(Above code is for Reading a File and adding data to the List by filling the object.)
The function is reading file of size 10 MB which is inside a zip file, first I am extracting the zip files, then reading the data, using this function and storing it into List and then deleting the extracted zip files. It is working for approximately 6L(6,00,000) Data but above that data it throws exception.
I want to read More data 10L(10,00,000) how should I do that ?
Do not return a list. Instead, use yield return to just run through the data:
private IEnumerable<i1LogThinDO> ReadCurrentFile(string currentExtractedFile,
PurgingDetails purgingParams)
{
using (StreamReader sr = new StreamReader(currentExtractedFile))
{
string currentLine = string.Empty;
Dictionary<string, string> ColumnNamesDictionary = null;
while ((currentLine = sr.ReadLine()) != null)
{
if (currentLine.IsNotNullOrEmpty() && currentLine.Contains("Æ"))
{
string[] columnNames = currentLine.Split(new char[] { 'Æ' });
ColumnNamesDictionary = FillColumnNameDictionary(columnNames);
if (CheckForValidConditions(ColumnNamesDictionary, purgingParams))
{
yield return FillThinLogDO(ColumnNamesDictionary);
}
}
}
}
}
This way, the ball is in the caller's yard. The caller must be able to process the data returned from this method without keeping them all in memory. This could mean that you have to redesign the calling methods as well, but it would bring a huge cut down in memory footprint of the application if you could do all the processing without keeping the data in memory.

How to bind String[] values in listview using hashmap in android?

Hi I am trying to get values using hashmap<> using .net web services in android. I have custemized adapter, I am trying to do this.
SoapObject folderResponse = (SoapObject)envelope.getResponse();
Log.i("AllFolders", folderResponse.toString());
String[] folderslist = new String[folderResponse.getPropertyCount()];
//getting values using folderslist.
ArrayList<HashMap<String, String>> hashfoldersList = new ArrayList <HashMap<String, String> >();
//But I want hashfoldersList list in my custamized adapter.
for(i=0; i<folderResponse.getPropertyCount(); i++) {
SoapObject SingleFolder = (SoapObject)folderResponse.getProperty(i);
Log.i("SingleFolder", SingleFolder.toString());
ID= SingleFolder.getProperty(0).toString();
KEY_Name = SingleFolder.getProperty(1).toString();
ParentID = SingleFolder.getProperty(2).toString();
CreatedBy= SingleFolder.getProperty(3).toString();
System.out.println(ID);
System.out.println(KEY_Name);
System.out.println(ParentID);
System.out.println(CreatedBy);
SoapPrimitive Record =(SoapPrimitive) SingleFolder.getProperty(1);
Log.i("Record", Record.toString());
{
folderslist[i] = SingleFolder.getProperty(0).toString();
}
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML from URL
org.w3c.dom.Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = (NodeList) doc.getElementsByTagName(ID);
// looping through all song nodes <song>
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(ID, parser.getValue(e, ID));
map.put(KEY_Name, parser.getValue(e, KEY_Name));
map.put(ParentID, parser.getValue(e, ParentID));
map.put(CreatedBy, parser.getValue(e, CreatedBy));
foldersList.add(map);
}
listview = (ListView)findViewById(R.id.listview);
adapter=new LazyAdapter(this, hashfoldersList);
//My custemized adapter.
listview.setAdapter(adapter);
listview.setOnItemClickListener(this);
}
}
Please suggest, how to get values in list using ArrayList> hashfolderlist, as I am using string[] folderlist. when I am inserting hashfolderlist, it is giving error. Please suggest. thanks
mate you should have a simple adapter to take the strings and put it inside a listview.
second you should have 2 textviews
SimpleAdapter adapter = new SimpleAdapter(this, list,
R.layout.your_activity, new String[] { "", "" },
new int[] { R.id.textview1, R.id.textView2 }
);
listView1.setAdapter(adapter);
hope it helps you!!

Resources