Google Sheets formula that changes text only between parenthesis - google-sheets

I'm trying to format a sheet that creates a grid between names; the names are automatically mirrored on one axis using the = link method so that it's user-friendly.
However, linking cells via = doesn't copy any formatting and only uses the native formatting of the cell. I want half of the text to be a different color (lighter grey and not bold, ideally). Since you cannot adjust the text of a mirrored cell and it doesn't mirror formatting, I was thinking I could backdoor it through a formula.
The wise thing would be to either swallow that it doesn't work that way and go with the uglier formatting, or to unlink them and simply allow the user to manually enter the data for neatness. However, I figured it'd be a good learning exercise if I could figure out a way to selectively format only text within parentheticals.
Is there a way to use a formula to color text only within parenthesis?

To format the text in parentheses, try
function formatParenthesis() {
const range = SpreadsheetApp.getActiveRange()
const spec = { regex: /\(.*\)/gi, textColor: 'grey', bold: true, italic: true };
const values = range.getDisplayValues();
let match;
const formattedText = values.map(row => row.map(value => {
const richText = SpreadsheetApp.newRichTextValue().setText(value);
const format = SpreadsheetApp.newTextStyle()
.setForegroundColor(spec.textColor)
.setBold(spec.bold)
.setItalic(spec.italic)
.build();
while (match = spec.regex.exec(value)) {
richText.setTextStyle(match.index, match.index + match[0].length, format);
}
return richText.build();
}));
range.setRichTextValues(formattedText);
}
references
RichTextValueBuilder
setTextStyle

Related

Google sheets conditional formatting to colour cell if the same cell in another sheet is not empty

I have 2 sheets A and B. I want sheet A to colour cells if the exact same cell in sheet B is not empty. For example if cell A1 in sheet B has a string, then cell A1 in sheet A will be coloured.
Let's say I want to do this to compare a large range, how should I go about doing this?
Example: https://docs.google.com/spreadsheets/d/1P3Ob_mclpXWmILfKwD4R6JN2wAYPUcNZlmtF9LxilV0/edit?usp=sharing
Cells A2:C2, D5 and K2 in sheet B are not empty. So the corresponding cells in sheet A will be coloured red.
You can use the following formula as a conditional formatting rule:
=NOT(ISBLANK(INDIRECT("B!"&address(row(),column()))))
(the formula in A!A2 is there to just show you what happens in sheet B)
Explanation:
Not familiar how this could be done with a custom conditional formatting formula so wait for other guys to help you out with that.
However, I can offer you a Google Apps Script solution.
The following script will check for the data range in sheet B and it will construct a color array. An element of this array will have the white hex color #ffffff" if the value in the values array is empty, or a red color #ff0000 if the value is not blank.
Then it will color sheet A based on this color array in one go. The script is relatively fast even for large ranges.
Solution / Workaround:
Don't forget to adjust "sheet A" and "sheet B" to the name of your sheets.
function colorCells(){
const ss = SpreadsheetApp.getActive();
const sheetToColor = ss.getSheetByName("sheet A");
const sheetToCheck = ss.getSheetByName("sheet B");
const bValues = sheetToCheck.getDataRange().getValues();
const aColors=bValues.map(r=>r.map(v=>v==''?"#ffffff":"#ff0000"));
sheetToColor.getRange(1,1,sheetToCheck.getLastRow(),sheetToCheck.getLastColumn()).
setBackgrounds(aColors);
}
How to use that:
Click on Tools => Scipt editor, copy, paste & save the aforementioned code and then execute it by clicking on the play button.
If you want this to work "automatically" then you can set up a time trigger to execute this function for you every n minutes.
Bonus code:
You can do the same operation but on a more user-interactive way. Again, copy, paste & save the following script to the script editor but this time don't execute it as it can work by itself.
The following script will change the color of a cell in sheet A upon user edits on the same cell in sheet B:
function onEdit(e) {
// adjust this to your needs:
const sheetToColorName = "sheet A";
const sheetToCheckName = "sheet B";
const rng = e.range;
const cell = rng.getA1Notation();
if (rng.getSheet().getName()==sheetToCheckName){
const sheetToColor = e.source.getSheetByName(sheetToColorName);
if(rng.getValue()!=''){
sheetToColor.getRange(cell).setBackground("#ff0000"); //red
}
else {
sheetToColor.getRange(cell).setBackground("#ffffff"); //white
}
}
}

amCharts 4: display legend tooltip on truncated (with ellipsis) values only

I've enabled the legend on a amCharts v4 chart with the following code but I have issues with ellipsis:
// Add legend
chart.legend = new am4charts.Legend();
chart.legend.fontSize = 11;
// Truncate long labels (more than 160px)
chart.legend.labels.template.maxWidth = 160;
chart.legend.labels.template.truncate = true;
chart.legend.labels.template.fullWords = true;
// Set custom ellipsis as default one is not displayed correctly
chart.legend.labels.template.ellipsis = "...";
// Set tooltip content to name field
chart.legend.itemContainers.template.tooltipText = "{name}";
As you can see I had to set a custom ellipsis property because Firefox v76 displayed €| instead of … on the truncated legend labels. It happens even on the sample on the amChart website but, surprisingly, not if I open the same URL in a private tab... How can I fix that?
Then I would like to display the tooltip on the legend only for truncated labels. Adding an adapter:
chart.legend.itemContainers.template.adapter.add("tooltipText", function(text, target) {
// 'text' here contains the non-truncated string
return "My modified " + text;
})
of course works, but how can I identify inside the adapter code if the label that I'm processing is truncated and clear the text variable? It doesn't make sense to display tooltips for non-truncated legend items.
Not sure the most ideal way but...
You get the text inside the adaptor callback.
You can add a text.length check like:
chart.legend.itemContainers.template.adapter.add("tooltipText", function(text, target) {
// 'text' here contains the non-truncated string
return text.length > someValyeBasedOnMaxwidth> ? "My modified " + text: "";
})
I found the answer about the tooltip adapter; this works:
chart.legend.itemContainers.template.adapter.add("tooltipText", function(text, target) {
if (!target.dataItem.label.isOversized) {
// Legend label is NOT truncated, disable the tooltip
return "";
}
// Legend label is truncated, display the tooltip
return text;
})
Still I don't know why the ellipsis are not displayed correctly without setting the property...

Highlight Row if Value in Column is above 0 - Google Spreadsheet

I am trying to get a Google spreadsheet to automatically highlight all rows in a spreadsheet where the value in a particular column is above 0. I have looked for a few solutions but haven't got it to work.
I have got various metrics in the columns, so say I want to highlight all rows, in which column "I" has a value of more than zero.
Can someone help me with this?
On the conditional formatting page choose "Custom formula is" from the list of options available and then in the text field type:
=$I:$I>0
Select your formatting options and then in the range field type the range. For example:
A2:Z100
Because only to be applied to a single column there is a simpler version (that I have complicated so that text is not highlighted):
Clear formatting, select ColumnI and Format, Conditional formatting..., Format cells if... Custom formula is and:
=and(isnumber(I1),I1>0)
with fill of choice and Done.
If to format not just the relevant cell but the entire row then change the Apply to Range (say to A1:Z1000) and add anchors ($s) as below:
=and(isnumber($I1),$I1>0)
The only solution I'm aware of would be to write a script.
Link: Google Apps Scripts
The following is not pretty, but it works:
function myFunction() {
var I_INDEX = 1;
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Highlight rows");
var dataRange = sheet.getDataRange();
var dataValues = dataRange.getValues();
for (var i=1; i<=dataRange.getNumRows(); i++) {
var row = sheet.getRange(i, 1, 1, 2);
if (dataValues[i-1][I_INDEX] > 0) {
row.setBackground("red");
}
}
}
See example, use "Tools" --> "Script Editor..." to view/run the script.

conditional formatting not working

(am using PHPExcel 1.7.8)
I create a sheet and populate it with a table of numeric data. Then Excel refuses to apply conditional formatting of the 3-color-transition type to the numeric data.
That means, too:
1) I can use conditional formatting of the "top 10 values" kind
2) If I populate right next to the generated table few cells with numbers then I can use the cond formatting of transitional kind
3) If I copy two cells from the generated table somewhere else in a simple copy/paste fashion still can't use the transitional formatting
4) If I copy two cells from the generated table somewhere else using the "just the value"-pasting I do can use the transitional formatting
Another important observation here is, that when I select a cell of the generated table and click into the value bar - right at that moment - the cell changes its color to what it should be regarding the conditional formatting!
This is somewhat similar to another phenomena I observed with PHPExcel generated spreadsheets. Sometimes it happens that, when I double click into a cell to get into editing mode - the cell turns pit black. But still I can change the value.
There seems to be something wrong with how a cell is represented in the Excel-file I guess. Something related to the control of the coloring ... !?
I could of course copy/(value-)paste everything. But maybe I am just using PHPExcel the wrong way? Or there is a quick way to convert an Excel file at once in a useful way?
The full code I use is this:
$excelWorkbook = null;
if(file_exists($filename)) {
$reader = PHPExcel_IOFactory::createReader("Excel2007");
$excelWorkbook = $reader->load($filename);
} else {
$excelWorkbook = new PHPExcel();
}
$sheet = $excelWorkbook->getSheetByName($tabName);
if ($sheet !== null) {
$excelWorkbook->removeSheetByIndex($excelWorkbook->getIndex($sheet));
}
$sheet = new PHPExcel_Worksheet($excelWorkbook, $tabName);
$sheet = $excelWorkbook->addSheet($sheet);
$columns = array_keys($targetArray);
$rows = array_keys($targetArray[$columns[0]]);
for($i = 0; $i < count($columns); $i++){
$sheet->setCellValueByColumnAndRow($i+1,1,$columns[$i]);
}
for($i = 0; $i < count($rows); $i++){
$sheet->setCellValueByColumnAndRow(0,$i+2,$rows[$i]);
}
for($i = 0; $i < count($columns); $i++){
for($j = 0; $j < count($rows); $j++) {
$sheet->setCellValueByColumnAndRow($i+1, $j+2, $targetArray[$columns[$i]][$rows[$j]]);
}
}
$excelWorkbook->setActiveSheetIndex($excelWorkbook->getIndex($sheet));
$xlsx = new PHPExcel_Writer_Excel2007($excelWorkbook);
$xlsx->save($filename);
The workaround-type solution is to select all cells in the respective sheet and choose for background color 'none'.
Apparently the cells are colored white and this coloring overlays the conditional coloring.
This may be a bug due to the fact that for solid fills in cells Excel reverses the meaning of foreground and background colours but in conditional (dxf) formats it doesn't.
Or, to put it another way background and foreground are stored differently for cell and conditional formats.
I encountered this issue in the Perl Excel::Writer::XLSX module.

how to make a Text prevent the inputs more than 'x' number of digits?

My question is:
I want the Text field in Eclipse RCP to allow only the digits to be keyed in as inputs and the requirement is that it should allow only up to 'x' (let's say x=5) characters.
How can I accomplish it in RCP ?
I've tried the code like:
txtInput.addListener(SWT.Verify, new DecimalText(
txtInsuranceValue, 8, 1000.00));
where txtInputis a Text field. But this listener failed when I made repeated input into this field at run time.
Any alternatives please ?
This will set the maximum number of characters in your Text control to five and allow only digits to be entered:
txtInput.setTextLimit(5);
txtInput.addVerifyListener(new VerifyListener() {
public void verifyText(VerifyEvent event) {
// Assume we allow it
event.doit = true;
String text = event.text;
char[] chars = text.toCharArray();
//Don't allow if text contains non-digit characters
for (int i = 0; i < chars.length; i++) {
if (!Character.isDigit(chars[i])) {
event.doit = false;
break;
}
}
}
});
EDIT: I've modified my answer to allow a user to also set text with "setText(String string)" while still disallowing non-digit characters.
In general, solutions like adding verifyListeners/focusListeners are not complete and won't work with all situations. For example, what happens when the user copy-pastes some text into this text box?
If all you want is to get numerical inputs from the user, you should be using Spinner widget instead of Text widget. You could easily set the minimum and maximum limits on the Spinner.
See the snippets for more usage.

Resources