Forum Discussion

mj786's avatar
mj786
Copper Contributor
Oct 26, 2025

Excel conditional formula

Hi

i have a problem understanding this

 I want to color highlight numbers from row 2 that is row 1 + 5

I mean if any number from row 2 + 5 equal to any number in row 1 to be formatted and filled with a color

 

What formula should i put?

9 Replies

  • Lorenzo's avatar
    Lorenzo
    Silver Contributor

    Correct (bad copy/paste I'm gonna fix...):

    [1, "wxyz", true, 3].map((x: number) => x + 5)    // => [6, "wxyz5", 6, 8]

    Good to know. As a newby I will avoid though:

    const abc: number = "abc"       // type string is not assignable to type number
    console.log(abc + 2, ~~abc + 2) // => abc2, 2

    Thanks for the Stack Overflow link

  • Lorenzo's avatar
    Lorenzo
    Silver Contributor
    [1, "wxyz", true, 3].map(x => +x + 5)          // => [6, Nan, 6, 8]
    [1, "wxyz", true, 3].map(x => Number(x) + 5)   // => [6, Nan, 6, 8]
    [1, "wxyz", true, 3].map((x: number) => x + 5)  // => [6, "wxyz5", 6, 8]
    [1, 0/0, true, 3].map((x: number) => x + 5)    // => [6, Nan, 6, 8]

     

    • SergeiBaklan's avatar
      SergeiBaklan
      Diamond Contributor

      At least in Excel environment it shall be

      [1, "wxyz", true, 3].map((x: number) => x + 5) // => [6, wxyz5, 6, 8]

      Yes, editor reports a problem "type string is not assignable to type number" if we use something like

      const abc: number = "abc"

      but actually it works

      console.log(abc + 2, ~~abc + 2)     // => abc2, 2

      On the other hand yes, above is not a good practice which better to avoid.

      Just in case, whatever to number conversion table is here javascript - parseInt vs unary plus, when to use which? - Stack Overflow

  • Lorenzo's avatar
    Lorenzo
    Silver Contributor

    A TypeScript option for the exercise only (my 3rd script - be gentle please)
    NB: Do not use it with large ranges

    // TypeScript: Color cells on condition:
    //  IF cell value in Range_to_color + Increment = any cell value in Range_of_references
    //  THEN color cell in Range_to_color
    //
    //  ASSUMPTION: Range_of_references & Range_to_color consist of numbers only (empty cells OK)
    function main(
      workbook: ExcelScript.Workbook,
      Range_of_references: string = "A2:F2",
      Range_to_color: string = "A3:F3",
      Increment: number = 5
    ) {
    
      function normalizeAddress(address: string): string {
        // Trim and convert to uppercase for consistent address validation
        return address.trim().toUpperCase();
      }
    
      function isValidAddress(address: string): boolean {
        // Basic regex to validate Excel-style range references (e.g., A1:B3, B10:C10...)
        const regExcelRange: RegExp = /^[A-Z]+[1-9][0-9]*:[A-Z]+[1-9][0-9]*$/;
        return regExcelRange.test(normalizeAddress(address));
      }
    
      // Validate the input address format (e.g., "A1", "B100", "AZ35")
      if (!isValidAddress(Range_of_references) || !isValidAddress(Range_to_color)) {
        // Execution stops on throw (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw)
        throw new Error("Please enter valid range address(es) like A1:D1, C4:G4, ...");
      }
    
      // Get active worksheet and ranges
      const worksheet = workbook.getActiveWorksheet();
      const sourceRange = worksheet.getRange(Range_of_references);
      const targetRange = worksheet.getRange(Range_to_color);
    
      // Count columns in targetRange
      const targetColumns: number = targetRange.getColumnCount();
    
      // Flatten sourceRange (workaround to .flat() that raises a warning in Excel TS console)
      const flattenedSource = sourceRange.getValues()
        .reduce((acc, row) => acc.concat(row), []);
    
      // Iterate cells in targetRange
      for (let i = 0; i <= targetColumns; i++) {
        const currentCell = targetRange.getCell(0, i);
        // Invoking read methods inside of a loop could lead to slow perf.:
        const currentValue = Number(currentCell.getValue());
    
        // Iterate flattenedSource
        for (let j = 0; j <= targetColumns; j++) {
          // If currentValue (in targetRange) + Increment = current flattenedSource value...
          if (flattenedSource[j] === currentValue + Increment) {
            // Color the cell in targetRange
            currentCell.getFormat().getFill().setColor("#C1F0C8");
            break
          }
        }
      }
    }

     

    • SergeiBaklan's avatar
      SergeiBaklan
      Diamond Contributor

      Another point it's hard to test with regex all valid addresses, from A1 to XFD1048576. Expression will be too complex. However, OfficeScript checks itself if we use correct range, thus we may rely on it and use try/catch. In addition it's only to add our own rule which doesn't allow to run script with single cell ranges.  Something like

      function main(
          workbook: ExcelScript.Workbook,
          Range_of_references: string = "A2:F2",
          Range_to_color: string = "A3:F3",
          Increment: number = 5
      )
      
      // see https://techcommunity.microsoft.com/discussions/excelgeneral/excel-conditional-formula/4464321
      
       {
      
          const worksheet = workbook.getActiveWorksheet()
          if (!Range_of_references.includes(":") || !Range_to_color.includes(":")) {
              throw new Error(`Keep ":" in range addresses`)
          }
          try {
              worksheet.getRange(Range_of_references)
              worksheet.getRange(Range_to_color)
          } catch (error) {
              console.log(`Incorrect (${Range_of_references}) or (${Range_to_color}) address. Please inspect and run again.`)
              return
          }
      
          const sourceRange = worksheet.getRange(Range_of_references)
          const targetRange = worksheet.getRange(Range_to_color)
          const flattenedSource = sourceRange.getValues()[0]
          const incremented = targetRange.getValues()[0].map(x => +x + Increment)
      
          targetRange.getFormat().getFill().clear()
          Array.from(incremented.keys())
              .filter(n => incremented
                  .map(x => flattenedSource.includes(x))[n])
              .map(m => targetRange.getCell(0, m).getFormat().getFill().setColor("lightgreen"))
      
      }
      • Lorenzo's avatar
        Lorenzo
        Silver Contributor

        SergeiBaklan​ 

        Agreed, regex isn't the appropriate approach (did it for the exercise) & your try...catch approach should do a better jon

        Good training material for me :) who started with JS/TS a few days ago. Very concise approach:

        const flattenedSource = sourceRange.getValues()[0]
        const incremented = targetRange.getValues()[0].map(x => +x + Increment)
        
        targetRange.getFormat().getFill().clear()
        Array.from(incremented.keys())
            .filter(n => incremented
                .map(x => flattenedSource.includes(x))[n])
            .map(m => targetRange.getCell(0, m).getFormat().getFill().setColor("lightgreen"))
    • SergeiBaklan's avatar
      SergeiBaklan
      Diamond Contributor

      Great approach. Here is with slightly modified second part

      function main(
          workbook: ExcelScript.Workbook,
          Range_of_references: string = "A2:F2",
          Range_to_color: string = "A3:F3",
          Increment: number = 5
      )
      
      // see https://techcommunity.microsoft.com/discussions/excelgeneral/excel-conditional-formula/4464321
      
       {
      
          function normalizeAddress(address: string): string {
              // Trim and convert to uppercase for consistent address validation
              return address.trim().toUpperCase();
          }
      
          function isValidAddress(address: string): boolean {
              // Basic regex to validate Excel-style cell references (e.g., A1:B3, B10:C10...)
              const regex = /^[A-Z]+[1-9][0-9]*:[A-Z]+[1-9][0-9]*$/;
              return regex.test(normalizeAddress(address));
          }
      
          // Validate the input address format (e.g., "A1", "B100", "AZ35")
          if (!isValidAddress(Range_of_references) || !isValidAddress(Range_to_color)) {
              // Execution stops on throw (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw)
              throw new Error("Please enter valid range address(es) like A1:D1, C4:G4, ...");
          }
      
          // Get active worksheet and ranges
          const worksheet = workbook.getActiveWorksheet();
          const sourceRange = worksheet.getRange(Range_of_references);
          const targetRange = worksheet.getRange(Range_to_color);
      
      
          /////////////////////////////////////////////////////////////////////
          // Another variant
          const flattenedSource = sourceRange.getValues()[0]
          const incremented = targetRange.getValues()[0].map(x => +x + Increment)
      
          targetRange.getFormat().getFill().clear()
          Array.from( incremented.keys())
                  .filter(n => incremented
                      .map(x => flattenedSource.includes(x))[n])
                  .map( m => targetRange.getCell(0, m).getFormat().getFill().setColor("lightgreen"))
          // end of another variant
          /////////////////////////////////////////////////////////////////////////
      
      
      /*
          // Count columns in targetRange
          const targetColumns: number = targetRange.getColumnCount();
      
          // Flatten sourceRange (workaround to .flat() that raises a warning in Excel TS console)
          const flattenedSource = sourceRange.getValues()
              .reduce((acc, row) => acc.concat(row), []);
      
          // Iterate cells in targetRange
          for (let i = 0; i <= targetColumns; i++) {
              const currentCell = targetRange.getCell(0, i);
              // Invoking read methods inside of a loop could lead to slow perf.:
              const currentValue = Number(currentCell.getValue());
      
              // Iterate flattenedSource
              for (let j = 0; j <= targetColumns; j++) {
                  // If currentValue (in targetRange) + Increment = current flattenedSource value...
                  if (flattenedSource[j] === currentValue + Increment) {
                      // Color the cell in targetRange
                      currentCell.getFormat().getFill().setColor("lightgreen")  //   ("#C1F0C8");
                      break
                  }
              }
          }
      */
      
      }

       

  • Lorenzo's avatar
    Lorenzo
    Silver Contributor

    Hi

    Conditional Formatting rule with formula that Applies to $A$3:$F$3:

    =SUM( MATCH( A3 + 5, $A2:$F2, 0 ) )

    or, if you run Excel >/= 2021

    =SUM( XMATCH( A3 + 5, $A2:$F2 ) )

     

Resources