R/read_npx_excel.R

Defines functions read_npx_excel

Documented in read_npx_excel

#' Help function to read long or wide format
#' `r ansi_collapse_quot(x = get_olink_data_types(), sep = "or")` data from
#' Microsoft
#' `r ansi_collapse_quot(x = get_file_ext(name_sub = "excel"), sep = "or")`
#' files exported from Olink software in R.
#'
#' @author
#'   Klev Diamanti
#'   Christoffer Cambronero
#'   Kathleen Nevola
#'
#' @inherit .read_npx_args params
#' @inherit read_npx_delim return
#' @param file Path to Olink software output excel file in wide or long format.
#' Expected file extensions
#' `r ansi_collapse_quot(get_file_ext(name_sub = "excel"), sep = "or")`.
#'
#' @keywords internal
#'
#' @seealso
#'   \code{\link{read_npx}}
#'   \code{\link{read_npx_parquet}}
#'   \code{\link{read_npx_zip}}
#'   \code{\link{read_npx_format}}
#'   \code{\link{read_npx_delim}}
#'
read_npx_excel <- function(file,
                           out_df = "arrow") {

  # Check input ----

  # check if file exists
  check_file_exists(file = file,
                    error = TRUE)

  # check that the requested output df is ok
  check_out_df_arg(out_df = out_df)

  # check if readxl is available ----

  rlang::check_installed(
    pkg = "readxl",
    call = rlang::caller_env()
  )

  # read data ----

  # tryCatch in case reading the delimited file fails
  tryCatch(
    {

      # read the entire excel file
      df_olink <-  readxl::read_excel(path = file,
                                      col_names = FALSE,
                                      .name_repair = "minimal")

      # if the first row has 1 or more NAs we can safely guess that this is a
      # Olink file in wide format so we have to call the column names V1, V2...
      if (any(is.na(df_olink[1L, ]))) {

        colnames(df_olink) <- paste0("V", seq_len(ncol(df_olink)))
        df_olink <- df_olink |>
          dplyr::as_tibble()

      } else {

        colnames(df_olink) <- df_olink[1L, ] |> as.character()
        df_olink <- df_olink |>
          dplyr::as_tibble() |>
          dplyr::slice(
            2L:dplyr::n()
          )
      }

    }, error = function(msg) {

      cli::cli_abort( # nolint: return_linter
        c(
          "x" = "Unable to open excel file: {.file {file}}",
          "i" = "Check if the input {.arg file} is an excel file."
        ),
        call = rlang::caller_env(),
        wrap = FALSE
      )

    }
  )

  if (length(names(df_olink)) == 1L) {

    cli::cli_warn(
      message = c(
        "i" = "The excel file {.file {file}} has only one column!"
      ),
      call = rlang::caller_env(),
      wrap = FALSE
    )

  }

  # top row is as expected for the corresponding format

  read_npx_format_colnames(df = df_olink, file = file)

  # if needed convert the object to the requested output
  df_olink <- convert_read_npx_output(df = df_olink,
                                      out_df = out_df)

  # return ----

  return(df_olink)

}

Try the OlinkAnalyze package in your browser

Any scripts or data that you put into this service are public.

OlinkAnalyze documentation built on June 24, 2026, 1:06 a.m.