I'm accessing a public Google Docs Spreadsheet using the Google Sheets API. The API says that when you query a list-feed for a worksheet, you get back a list of rows excluding the first row, which is the header row (by convention).
Is there a way to access the header row? I see that you can use the cells feed to request specific cells:
// Fetch column 4, and every row after row 1.
URL cellFeedUrl = new URI(worksheet.getCellFeedUrl().toString()
+ "?min-row=2&min-col=4&max-col=4").toURL();
CellFeed cellFeed = service.getFeed(cellFeedUrl, CellFeed.class);
Is there another way that is more explicit, to retrieve the header row?
I searched long and hard, but it appears there is no semantically explicit way to grab headers out of a spreadsheet. As I mentioned in the question, you can use the cell feed so this is what I did:
URL cellFeedUrl = new URL(worksheet.getCellFeedUrl().toString() + "?min-row=1&max-row=1");
CellFeed cellFeed = service.getFeed(cellFeedUrl, CellFeed.class);
for(CellEntry cellEntry : cellFeed.getEntries()) {
System.out.print(cellEntry.getCell().getValue() + ",");
}
System.out.println();
The important part is the ?min-row=1&max-row=1 part. This gives you all the cells in the first row of the sheet. By convention, the very first row in a worksheet is treated as the header.
getTags()
this might return an iterable with "name", "address", "manager", "employeeid"."
https://developers.google.com/gdata/javadoc/com/google/gdata/data/spreadsheet/CustomElementCollection#getTags()
Example - ListDemo.java
public void printAndCacheEntry(ListEntry entry) {
// We only care about the entry id, chop off the leftmost part.
// I.E., this turns http://spreadsheets.google.com/..../cpzh6 into cpzh6.
String id = entry.getId().substring(entry.getId().lastIndexOf('/') + 1);
// Cache all displayed entries so that they can be updated later.
entriesCached.put(id, entry);
out.println("-- id: " + id + " title: " + entry.getTitle().getPlainText());
for (String tag : entry.getCustomElements().getTags()) {
out.println(" <gsx:" + tag + ">"
+ entry.getCustomElements().getValue(tag) + "</gsx:" + tag + ">");
}
}
http://gdata-java-client.googlecode.com/svn-history/r497/trunk/java/sample/spreadsheet/list/ListDemo.java
I have never used this, so not 100% sure. But looks like what you want.
Related
I am doing a selenium test against a web page which returns a table with some rows and columns showing payment data. I'm trying to strip some characters/words from the result of the XPATH i'm using because i dont need the part while doing an assertion (check if the data in table is correct).
Normally the webpage also returns a "Dropdown Button" as text (there is an icon), just before the identification number (e.g 168.3285.6021 as seen below).
What i used is it.set(it.next().replaceAll("DropDown Arrow ","")); so the DropDown Arrow text is replaced with nothing, which only works for the first line, but the other 2 lines don't get replaced. Any tips?
public void check_receivals() {
// Check how many lines and assert the size (from xpath)
List<WebElement> Receivals = driver.findElements(By.xpath("//*[#id='received-overview']//div[#class='bdpo-overview-table-row']/div[#class='claims']"));
System.out.println(Receivals.size() + " receival lines found");
assertEquals(7, Receivals.size());
// Test data to compare against..aka expectedResultList
List<String> expectedResultList = new ArrayList<>();
expectedResultList.add ("168.3285.6021\n" + "Payment 2015\n" + "01-01-2015\n" + "€ 246");
expectedResultList.add ("143.8407.8413\n" + "Payment 2015\n" + "01-01-2015\n" + "€ 233");
expectedResultList.add ("154.2841.2407\n" + "Payment 2015\n" + "01-01-2015\n" + "€ 253");
// Assert
List<WebElement> ReceivalLines = driver.findElements(By.xpath("//*[#id='received-overview']//div[#class='bdpo-overview-table-row']/div[#class='claims']"));
List<String> ReceivalLines_List = ReceivalLines.stream().map(WebElement::getText).collect(Collectors.toList());
ListIterator<String> it = ReceivalLines_List.listIterator();
while(it.hasNext()) {
it.set(it.next().replaceAll("DropDown Arrow ",""));
assertEquals(ReceivalLines_List, expectedResultList);
THe issue is that you are modifying the iterator as you are working with it. I would suggest making the replace part of the stream operation using the map function.
List<String> ReceivalLines_List = ReceivalLines.stream().map(WebElement::getText).map(s -> s.replaceAll("DropDown Arrow ","")).collect(Collectors.toList());
I am trying to produce several reports (i.e. N PPTX files) based on different inputs/for different users on the same PPTX template I created.
I have several preformatted XSLFTextShape on the PPTX template that contains a single XSLFTextParagraph already formatted (i.e. both the shape and the text). Each shape contains a particular placeholder that I need to substitute with a dynimic value. I have this value in a Map (placeholder,newValue). I am successful in updating the placeholder with the new value using:
textShape.clearText();
XSLFTextRun run = paragraph.addNewTextRun();
run.setText(newText);
So, when I produce the PPTX in output the text is updated but font color, font formatting, font size are changed compared to those I defined in the template. How can I keep the same formatting?
Any solutions to simply change the text while keeping original formatting?
Thanks in advance!
For everybody which may be interested in this topic in the future - I post the solution (working if one TextBox has a single Paragraph). This solution loops on all text boxes and in the case one contain one of the vales specified in the Placeholder->newValue map, it will update it maintaining the formatting.
public static void updateTextBoxesWithDesiredValues(XMLSlideShow ppt, Map<String, String> placeHolderDefinedValue) {
logger.info("ElapsedTime: " + tM.getTimeElapsedReadableFormat() + " ########## Updating single text box content...");
List<XSLFSlide> allSlides = ppt.getSlides();
int updatedElements = 0;
for (XSLFSlide currentSlide : allSlides) {
for (XSLFShape shape : currentSlide.getShapes()) {
if (shape instanceof XSLFTextShape) {
XSLFTextShape textBox = (XSLFTextShape) shape;
String elementTextContent = textBox.getText();
for (Object key : placeHolderDefinedValue.keySet()) {
if (elementTextContent.equals(key)) {
List<XSLFTextParagraph> textBoxParagraphs = textBox.getTextParagraphs();
List<XSLFTextRun> textBoxParagraphTextRuns = textBoxParagraphs.get(0).getTextRuns();
//System.out.println("########################## check paragraph number in textbox: " + textBoxParagraphs.size() + " - TextRuns: " + textBoxParagraphs.get(0).getTextRuns().size());
logger.info("ElapsedTime: " + tM.getTimeElapsedReadableFormat() + updatedElements + ") Updating: " + textBox.getText() + " --> " + placeHolderDefinedValue.get(key));
for (XSLFTextRun r : textBoxParagraphTextRuns) {
r.setText(placeHolderDefinedValue.get(key));
}
updatedElements++;
//break;
}
}
}
}
}
logger.info("ElapsedTime: " + tM.getTimeElapsedReadableFormat() + " Total Text Element Content Updated: " + updatedElements + " #########################");
}
It's kind of horrible - but yeah there's a reason they called it "POI".
Here's my approach to "only reset text" of an existing XSLFTextShape (that must have at least some text pre-set!):
textShape.getTextParagraphs().get(0).getTextRuns().get(0).setText(text);
for (int i = 1; i < textShape.getTextParagraphs().get(0).getTextRuns().size(); i++) {
textShape.getTextParagraphs().get(0).getTextRuns().get(i).setText("");
}
for (int i = 1; i < textShape.getTextParagraphs().size(); i++) {
textShape.getTextParagraphs().get(i).getTextRuns().stream().filter(tr -> !tr.getRawText().equals("\n")).forEach(tr -> tr.setText(""));
}
It will replace all existing text(paragraphs/runs) with "empty" text, but linebreaks can't be replaced for some reason. So this might leave you with some trailing lines - as they usually(!) are transparent this won't really hurt a lot.
.clearText / removing paragraphs either destoyed the formatting for me, or didn't work. Trying to reset the style (fontColor, fontFamily, fontSize, isBold, isItalit, ...) didn't result in satisfying results :(
We have a website that is built upon a ton of tables. Each cell within the rows is clickable. I am working on a way to dynamically build the cssSelector info by providing the table name and value I want to click on. I am getting close (I think).
Using the practice table at ToolsQA, say I want to build the cssSelector for the value "Taiwan".
It's cssSelector is: .tsc_table_s13 > tbody:nth-child(4) > tr:nth-child(3) > td:nth-child(2)
I am iterating through the table and have successfully been able to enter the cell using the value ("Taiwan") I specified, however, I'm not sure how to get the value of the row and column it is currently on.
Here is the code I am using so far:
driver.get("http://toolsqa.com/automation-practice-table/");
String table = ".tsc_table_s13 > tbody:nth-child(4)";
String cellValue = "Taiwan";
getCell(table, cellValue);
// Get the cell of a particular value
public static void getCell(String table, String value) throws IOException{
// Grab the table
WebElement tableName = driver.findElement(By.cssSelector(table));
// Now get all the TR elements from the table
List<WebElement> allRows = tableName.findElements(By.tagName("tr"));
// And iterate over them, getting the cells
for (WebElement row : allRows) {
List<WebElement> cells = row.findElements(By.tagName("td"));
// Print the contents of each cell
for (WebElement cell : cells) {
// System.out.println(cell.getText());
if (cell.getText().equals(value))
{
String cellValue = table + " > tr:nth-child(" + row. + ") > td:nth-child(" + cell + ")";
System.out.println(cellValue);
} // end if text equals
} // end for loop for cells
} // end for loop for all rows
} // end getCell function
So here's a quick example of how you can use XPath to find text in a table and get a reference to the element. You provide the text to search for and it gets inserted into an XPath. That XPath below, searches for a TD that contains that text. This is just a simple case. If you have a lot of repetitive text in your table, you'll have to post some examples so that I can update the code to take that into account.
String searchText = "China";
driver.get("http://toolsqa.com/automation-practice-table/");
WebElement e = driver.findElement(By.xpath("//td[text()='" + searchText + "']"));
System.out.println(e.getText()); // you can get the text in the cell
System.out.println(e.getAttribute("outerHTML")); // you can get the HTML of the TD
e.click(); // you can click the element also but in this case it won't do anything since it's just a TD with text
Is it possible to read the format of a cell from an excell sheet and determinde which words are bold or italic?
I can read and write to cells, and I also know that JExcel can write formatted cells. In formatted cells I mean that the text is italic, or bold.
Is it possible the read a cell data and determine which words are bold?
For instance I will have this in cell:
"A sample text from one excel cell"
I want to know that the string "excel cell" is bold, and the string "sample" is Italic.
Is this possible in JExcel, if not how would I do that in Java? Can somebody suggest an API?
Maybe a better approach would be to pares an xml file.
I don't know about JExcel, but I can tell you this is fairly easy to do in Apache POI. Here is a simple application to show one way it can be done. It isn't incredibly pretty, but it should be enough to get you started:
public static final void main(String... args) throws Exception
{
InputStream is = ExcelFormatTest.class.getResourceAsStream("Test.xlsx");
Workbook wb = new XSSFWorkbook(is);
Sheet sheet = wb.getSheetAt(0);
Cell cell = sheet.getRow(0).getCell(0);
XSSFRichTextString richText = (XSSFRichTextString)cell.getRichStringCellValue();
int formattingRuns = cell.getRichStringCellValue().numFormattingRuns();
for(int i = 0; i < formattingRuns; i++)
{
int startIdx = richText.getIndexOfFormattingRun(i);
int length = richText.getLengthOfFormattingRun(i);
System.out.println("Text: " + richText.getString().substring(startIdx, startIdx + length));
if(i == 0)
{
short fontIndex = cell.getCellStyle().getFontIndex();
Font f = wb.getFontAt(fontIndex);
System.out.println("Bold: " + (f.getBoldweight() == Font.BOLDWEIGHT_BOLD));
System.out.println("Italics: " + f.getItalic() + "\n");
}
else
{
Font f = richText.getFontOfFormattingRun(i);
System.out.println("Bold: " + (f.getBoldweight() == Font.BOLDWEIGHT_BOLD));
System.out.println("Italics: " + f.getItalic() + "\n");
}
}
}
Basically, you get a RichTextString object from a cell (make sure it is a String cell first, though), then iterate over the formatting runs and check the font for each one. It looks like the first run uses the Cell's CellStyle/font, so you have to look it up that way (you get an NPE if you try to get it from the RichTextString).
Once you have the font, you can get all of its attributes. Here is the Javadoc for POI's Font.
If you are using older, non-XLSX files, replace XSSF with HSSF in the class names, and you'll have to change the RichTextString code a bit to lookup the font using the font index. Here are the JavaDocs for XSSFRichTextString and HSSFRichTextString.
Running this with the following in Sheet 1, A1: "A sample text from one excel cell" gives the following results:
Text: A
Bold: false
Italics: false
Text: sample
Bold: true
Italics: false
Text: text
Bold: false
Italics: false
Text: from
Bold: false
Italics: true
Text: one
Bold: false
Italics: false
Text: excel cell
Bold: true
Italics: true
Here's how I'd do it in VBA. Maybe you can translate:
Sub ListBoldStrings()
Dim cell As Excel.Range
Dim i As Long
Dim BoldChars As String
Dim BoldStrings() As String
'replace "|" with a char that will not appear in evaluated strings
Const SEPARATOR_CHAR As String = "|"
Set cell = ActiveCell
With cell
For i = 1 To .Characters.Count
If .Characters(i, 1).Font.Bold Then
BoldChars = BoldChars + .Characters(i, 1).Text
Else
BoldChars = BoldChars + SEPARATOR_CHAR
End If
If Right$(BoldChars, 2) = WorksheetFunction.Rept(SEPARATOR_CHAR, 2) Then
BoldChars = Left$(BoldChars, Len(BoldChars) - 1)
End If
Next i
End With
BoldStrings = Split(BoldChars, SEPARATOR_CHAR)
For i = LBound(BoldStrings) To UBound(BoldStrings)
Debug.Print BoldStrings(i)
Next i
End Sub
I am read from a database column which stores data like
testing\n
testing\n
I am then using the jxl.write.WritableWorkbook methods to generate the excel file that will read from this column.
However when being displyed as excel There are no line break in the column data.
What is the reason and how should i resolve this?
You might try: WritableCellFormat.setWrap(true)
Look here: http://jexcelapi.sourceforge.net/resources/faq/
I searched the internet since i needed an answer and here it is...
From JExcel API FAQ:
How do I add a newline or carriage-return to a Label cell?
Use "\012" or "\n". Also make sure to turn on cell wrapping with WritableCellFormat.setWrap(true) or the newline will show up as a square (unknown character).
I tested it and it worked for "\012" or "\n" as i put also .setWrap(true) and i tested it with
WritableCellFormat times16format =
new WritableCellFormat(times16font);
times16format.setWrap(true);
times16format.setAlignment(Alignment.RIGHT);
times16format.setBorder(Border.ALL, BorderLineStyle.HAIR);
//Merge col[0-2] and row[0]
sheet.mergeCells(0, 0, 2, 0);
Label leftPartLabel =
new Label(
0,
0,
reportKingdomData + "\012" + dateData + " " + MyDateFormat.format(new Date()) + timeData + "\n" + MyTimeFormat.format(new Date()),
times16format);
sheet.addCell(leftPartLabel);
Insert Line In jxl JExcel API
Try this:
for (int row = 0; row<100; row++)
{
sheet.addCell(new Label(0,row,"Testing "+row);
}
Feel comfortable to let me know, if you are facing problem and don't forget to mark/upvote correct answer.