Студентам-технарям: автоматизируем оформление курсачей в таблицах Google

Когда учился в универе, было обязательное требование к оформлению расчетов задач, курсовых и т.п.: должны быть видны цифры, которые подставляются в формулу.

Т. е. так нельзя: S = π⋅R² = 314 [м²]
надо так: S = π⋅R² = 3,14⋅10² = 31,4 [м²]

Причина в том, что расчеты сдавались на бумаге, а профессорам проверять все это не видя цифр неудобно. Обычно расчеты мы делали в Excel, оформлять формулы и подстановку цифр приходилось вручную, и если исходные данные менялись, все автоматом пересчитывалось и оформление снова переделывали вручную. Я то понимал, что с такой примитивной задачей, как подставлять циферки в формулы, компьютер может справиться самостоятельно, но, как оказалось, такой возможности не реализовано ни в Mathcad, ни в Mathematica, ни в Excel.

В попытках найти подходящую программу я перепробовал много всего, но нашел только самописную BreadsCAD Владимира Воронова, такого же студента, что доказало, что я не один такой странный. Самописный продукт плохо интегрировался с другими программами, работал не без багов и, конечно, не был кроссплатформенным. А тогда, как раз стали появляться планшеты, реклама первого айпада взрывала интернет, демонстрируя запредельный уровень комфорта, и моей заветной мечтой стало делать курсовые, расположившись по-барски полулежа в кровати. Я даже начал изучать очень кроссплатформенный ActionScript 3.0, чтобы написать собственную программу, но, как оказалось, сделать это с нуля не так просто, хоть я и достиг в AS3.0 определенных успехов. В общем, до конца универа я оформлял курсачи вручную с легким чувством недовольства этим несовершенным миром.

Закончив универ, по работе иногда приходилось что-нибудь заскриптовать на VBA Excel и как-то меня осенило, что решение было совсем рядом. И вот, несколько лет назад, без всякой практической необходимости, а ради реализации юношеской мечты я сделал эту штуку MS Excel и Word (скрипт не только оформлял формулы в Excel, но и мог экспортировать расчет в Word с такими изысками, как дроби, квадратные корни, верхние и нижние индексы и т.п.). Нашел винтажное видео того, как это работало:


Простите за качество, записывал с экрана на телефон. Кстати эту штуку у меня даже купили сосед в студенческой общаге за 500 р. (Привет, Егор!)

А недавно пришло в голову более лаконичное решение в виде функции OpenCalc для Google Spreadsheets, получив действительной кроссплатформенный инструмент. Ну и не удержался, чтобы что-нибудь не посчитать этой штукой (учился я на теплоэнергетика, поэтому тема расчетов такая специфичная): https://docs.google.com/spreadsheets/d/14l52J9im79leO0ttKhyrHU4b03i-2bHONszPlgA0tFk

Если кому то понадобится, то вот код:

//Функция представляения формулы в нужном виде. Аргументы:
//symbol - ячейка с обозначением параметра
//value - ячейка с формулой и результатом
//unit - ячейка с размерностью
//symbolFormula - опционально - собственное изображение формулы, если обозначение стандартное обозначение не устраивает. Например если в С85: =СУММ(G81:R81), можем использовать свою формулу: =OpenCalc(B85;C85;D85;"=∑nз⁽³⁰⁾")
//pattern - опционально - шаблон, определсяет в каком виде будет выводиться формула. По умолчанию 'Symbol_SymbolFormula_ValueFormula_Value_Unit_', при необходимости можно убрать подстановку значений или размерность

function OpenCalc(symbol,value,unit,symbolFormula,pattern){
  pattern = pattern || 'Symbol_SymbolFormula_ValueFormula_Value_Unit_'; 
  if (unit != "") unit = ' [' + unit + ']';
  
  var arguments = SpreadsheetApp.getActiveRange().getFormula().split(' ').join('').slice(10,-1).split(';'); //аргументы функции OpenCalc (адреса ячеек), например = B11,C11,D11
  var formula = SpreadsheetApp.getActiveSpreadsheet().getRangeByName(arguments[1]).getFormula(); //вытаскиваем формулу из ячейки C11
  value = SpreadsheetApp.getActiveSpreadsheet().getRangeByName(arguments[1]).getDisplayValue(); //вытаскиваем значение из ячейки C11
  var symbolCol = SpreadsheetApp.getActiveSpreadsheet().getRangeByName(arguments[0]).getColumn(); //столбец с обозначениями параметров (B)
  var valueCol = SpreadsheetApp.getActiveSpreadsheet().getRangeByName(arguments[1]).getColumn(); //столбец с формулами и результатом вычисленй (С)
  var unitCol = SpreadsheetApp.getActiveSpreadsheet().getRangeByName(arguments[2]).getColumn(); //столбец с размерностью (D)
  
  
  var valueFormula='';
  if (symbolFormula === undefined) {
    symbolFormula = replaceFormula(formula,symbolCol);
    valueFormula = replaceFormula(formula,valueCol);};
  if (symbolFormula == valueFormula) valueFormula = ''; //если в формуле введены значения, а не ссылки на ячейки, например c = 3*10^8, подстановка значений не требуется
  var unitFormula = replaceFormula(formula,unitCol);  
  
  //подставляем части формулы в шаблон
  pattern = pattern.replace(/Symbol_/g, symbol);
  pattern = pattern.replace(/Value_/g, '=' + value);
  pattern = pattern.replace(/Unit_/g, unit);
  pattern = pattern.replace(/SymbolFormula_/g,symbolFormula);
  pattern = pattern.replace(/ValueFormula_/g, valueFormula);
  pattern = pattern.replace(/UnitFormula_/g, unitFormula);
  
  //улучшаем отображение на сколько это позволяет юникод
  pattern = pattern.split('^2').join('²');
  pattern = pattern.split('^3').join('³');
  pattern = pattern.split('*').join('·');
  pattern = pattern.split('+').join(' + ');
  pattern = pattern.split('-').join(' − ');
  pattern = pattern.split('/').join(' / ');
  pattern = pattern.split('SQRT').join('√');
  pattern = pattern.split('=').join(' = ');
   
  return pattern;
  
}

//функция замены в строке formula адресов ячеек на значения из столбца replaceCol - обозначения параметра (B), значения (C) или размерность (D)
function replaceFormula(formula,replaceCol) {
  return formula.replace( /(([A-Za-z]+\d+))[a-z\d]*/g, function(str) {
    var r=SpreadsheetApp.getActiveSpreadsheet().getRangeByName(str);
    return SpreadsheetApp.getActiveSheet().getRange(r.getRow(),replaceCol).getDisplayValue();} );
}
Теги:
gas, google apps script, vba, google spreadsheets

Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.