2016-03-29 1 views
1

У меня есть база данных MsSql, которая вычисляет промежуток времени между двумя датами в секундах. Это прекрасно работает. Затем я использую этот столбец в C# и записываю их в массив.Преобразование секунд в hhh: mm: ss в диаграмме

Этот массив является входом для диаграммы позже. До сих пор это хорошо работает, но я не могу найти способ отображения секунд в формате, таком как hhh: mm: ss, поскольку период времени может быть больше 24 часов.

Я пробовал ChartArea.AxisY.LabelStyle.Format = "hhmmss"; но это не работает вообще.

Есть ли у кого-нибудь идеи, как я мог это сделать?

EDIT: добавить данные таким образом:

chart2.Series.Clear(); 
chart2.ChartAreas.Clear(); 

Series BoxPlotSeries = new Series(); 

ChartArea ChartArea2 = new ChartArea(); 
ChartArea ChartArea3 = new ChartArea(); 

chart2.ChartAreas.Add(ChartArea2); 
chart2.ChartAreas.Add(ChartArea3); 
ChartArea2.Name = "Data Chart Area"; 
ChartArea3.Name = "BoxPlotArea"; 

BoxPlotSeries.Name = "BoxPlotSeries"; 
BoxPlotSeries.ChartType = SeriesChartType.BoxPlot; 
BoxPlotSeries.ChartArea = "BoxPlotArea"; 

chart2.Series.Add(BoxPlotSeries); 

Series Input1 = new Series(); 
Input1.Name = "Input1"; 
Input1.ChartType = SeriesChartType.Point; 
Input1.ChartArea = "Data Chart Area"; 
chart2.Series.Add(Input1); 
chart2.Series["Input1"].Points.DataBindY(InputArray); 
chart2.ChartAreas["BoxPlotArea"].AxisX.CustomLabels.Add(2, 0.0, "BoxPlot1"); 


chart2.Series["BoxPlotSeries"]["BoxPlotSeries"] = "Input1"; 
chart2.Series["BoxPlotSeries"]["BoxPlotShowMedian"] = "true"; 
chart2.Series["BoxPlotSeries"]["BoxPlotShowUnusualValues"] = "false"; 
chart2.Series["BoxPlotSeries"]["PointWidth"] = "0.5"; 
chart2.Series["BoxPlotSeries"].IsValueShownAsLabel = false; 
ChartArea2.Visible = false; 
ChartArea3.BackColor = Color.FromArgb(224,224,224); 
//I tried to format it this way but it didn't work 
//ChartArea3.AxisY.LabelStyle.Format = "{0:HHHmmss}"; 
chart2.ChartAreas["BoxPlotArea"].AxisX.LabelStyle.Angle = -90; 

EDIT2: А вот как я заселить входного массива

int[] InputArray = new int[1000000]; 

int c = 0; 
con.Open(); 
dr = cmd.ExecuteReader(); 
if (dr.HasRows)   
{ 
    while (dr.Read()) 
    { 
      int n; 
      if (int.TryParse(dr[0].ToString(),out n) == true) 
      { 
       InputArray[c] = Convert.ToInt32(dr[0].ToString()); 
       c++; 
      } 
    } 
} 
if (c == 0) { c = 1; } 
Array.Resize(ref InputArray, c - 1); 

EDIT 3: The Boxplot должен выглядеть следующим образом: enter image description here

В Excel формат для отображения часов больше, чем 24 называется "[ч]: мм: сс; @"

EDIT4:

Благодаря @TAW я почти удалось решить мой проблема. Я сделал некоторые изменения в его решение и пришел с этим:

В блоке диаграммы кода:

Значение «Макс» установлен ранее.

ChartArea3.AxisY.MajorTickMark.Interval = addCustomLabels(ChartArea3, BoxPlotSeries, 60 * 60, max); 





int addCustomLabels(ChartArea ca, Series series, int interval, int max) 
    { 
     int tickNo = 0; 
     ca.AxisY.CustomLabels.Clear(); 
     if(max/interval > 10) 
     { 
      interval = (max/10) - (max/10) % (60*30); 
      tickNo = (max/10) - (max/10) % (60*30); 
     } 
     if (max/interval <= 2) 
     { 
      interval = (max/4) - (max/4) % (60 * 15); 
      tickNo = (max/4) - (max/4) % (60 * 15); 
     } 
     for (int i = 0; i < max; i += interval) 
     { 
     CustomLabel cl = new CustomLabel(); 
     cl.FromPosition = i - interval/2; 
     cl.ToPosition = i + interval/2; 
     cl.Text = hhh_mm_ss(i); 
     ca.AxisY.CustomLabels.Add(cl); 
     } 
     return tickNo; 
    } 

Моя проблема в настоящее время, что иногда нет оси Lable (кроме 0:00) не отображается, даже если код проходит через него без каких-либо проблем.

Есть ли кто-нибудь и идея, что может быть неправильным?

+0

Какую схему вы используете? –

+0

Диаграмма Boxplot – FriendlyGuy

+0

Что такое структура пользовательского интерфейса и каково полное имя используемого вами типа? –

ответ

0

Ваша задача состоит из двух частей:

  • отображающих секунд в ххх: мм: сс
  • положить их в качестве меток на осях у

Для этого в C# нет подходящего date-time formatting string, поэтому мы не можем использовать встроенные автоматические метки и их форматирование.

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

Поэтому мы не можем использовать их.

Вместо этого мы должны будем добавить CustomLabels. Это не очень сложно, но делает несколько шагов.

Но давайте начнем с функции, которая преобразует int в нудную строку hhh:mm:ss; это должно сработать:

string hhh_mm_ss(int seconds) 
{ 
    int sec = seconds % 60; 
    int min = ((seconds - sec)/60) % 60; 
    int hhh = (seconds - sec - 60 * min)/3600; 
    return hhh > 0 ? string.Format("{2}:{1:00}:{0:00}", sec, min, hhh) 
        : min + ":" + sec.ToString("00"); 
} 

Возможно, он может быть оптимизирован, но для нашей цели это будет сделано.

Далее нам нужно создать CustomLabels. Они заменяют метки нормальной оси, и нам нужно добавить их в отдельный цикл над данными после каждой привязки.

Одна особенность в отношении них - их позиционирование. Который привкус между двумя значениями, которые нам нужно дать, FromPosition и ToPosition, как в единице значений оси.

Еще одно отличие в нормальных, автоматических меток является то, что он к нам, чтобы создать как многие или некоторые из них, как нужно нужно ..

Эта функция пытается создать номер, который будет идти до максимума у -значение и пространство, CustomLabels на заданном интервале:

void addCustomLabels(ChartArea ca, Series series, int interval) 
{ 
    // we get the maximum form the 1st y-value 
    int max = (int)series.Points.Select(x => x.YValues[0]).Max(); 
    // we delete any CLs we have 
    ca.AxisY.CustomLabels.Clear(); 
    // now we add new custom labels 
    for (int i = 0; i < max; i += interval) 
    { 
     CustomLabel cl = new CustomLabel(); 
     cl.FromPosition = i - interval/2; 
     cl.ToPosition = i + interval/2; 
     cl.Text = hhh_mm_ss(i); 
     ca.AxisY.CustomLabels.Add(cl); 
    } 
} 

первые параметры для вызова этого очевидны; последний, однако, является сложным:

Вам нужно выбрать интервал, который вы хотите, чтобы ваши метки имели. Это будет зависеть от различных деталей на диаграмме:

  • диапазон значений
  • размер области диаграммы
  • размер шрифта оси

я не сделал установить в функции любое специальное значение Font; CustomLabels используют одинаковые Font в качестве меток нормальной оси, то есть AxisY.LabelStyle.Font.

Для скриншоте я подготовил таблицу, как это:

ca.AxisX.Minimum = 0; 
ca.AxisY.MajorTickMark.Interval = 60 * 60; // one tick per hour 
addCustomLabels(ca, s, 60 * 30);   // one label every 30 minutes 

Я также добавил DataPoint этикетки для тестирования, чтобы показать значение ..:

series.Points[p].Label = hhh_mm_ss((int)y) + "\n" + y; 

Вот результат:

enter image description here

+0

Большое спасибо, что очень помогло. И извините за поздний ответ, у меня были грубые выходные с большим количеством работы для моего университета ... В большинстве случаев он отлично работает, но по мере того, как время менялось много, мне приходилось делать некоторые корректировки, как иногда варьируются от 30 минут до 400 часов. В главной статье я собираюсь написать то, что я сделал сейчас, может быть, вы видите, где я ошибся :) – FriendlyGuy

0

Если вы пытаетесь показать больше, чем 2 цифры часа, я думаю, что это должно работать для вас

//yourTimeSpan is the TimeSpan that you already have 
var hoursDouble = Math.Floor(yourTimeSpan.TotalHours); 
string hours; 
string minutes; 
string seconds; 

//check hours 
if(hoursDouble < 10) 
{ 
    hours = string.Format("0{0}", hoursDouble); 
} 
else 
{ 
    hours = hoursDouble.ToString(); 
} 
//check minutes 
if (yourTimeSpan.Minutes < 10) 
{ 
    minutes = string.Format("0{0}", yourTimeSpan.Minutes); 
} 
else 
{ 
    minutes = yourTimeSpan.Minutes.ToString(); 
} 
//check seconds 
if (yourTimeSpan.Seconds < 10) 
{ 
    seconds = string.Format("0{0}", yourTimeSpan.Seconds); 
} 
else 
{ 
    seconds = yourTimeSpan.Seconds.ToString(); 
} 

string formattedSpan = String.Format("{0}:{1}:{2}", hours, minutes, seconds); 

Update: Я думаю, что это должно решить проблему, которую вы видели с однозначными числами

+0

Ну, если я использую string formattedSpan = String.Format ("{0}: {1:00}: {2:00}", Convert.ToInt32 (yourTimeSpan.TotalHours), Convert.ToInt32 (yourTimeSpan.Minutes)% 60, Convert.ToInt32 (yourTimeSpan.Seconds)% 60); Это показывает мне часы трехзначных цифр, но я не знаю, как это сделать на графике. Не могли бы вы дать мне подсказку, как я могу это сделать? – FriendlyGuy

+0

Я обновил свой ответ –

+0

Спасибо Тиму, мое отредактированное решение также делает то же самое. Я предполагаю, что моя главная проблема заключается в форматировании метки оси, поскольку я не могу использовать промежутки времени там или есть способ? – FriendlyGuy

0

ОБНОВЛЕНИЕ: Этот ответ может быть весьма полезен для других читателей, но он в значительной степени пропускает проблемы OP. Я оставлю его, как он стоит, но это не поможет в создании специально отформатированные метки оси Y ..


Большинство проблем диаграмм вытекают из недействительных или бесполезных х значений. Следующее обсуждение пытается помочь избежать или обойти их.

Число является числом, и вы не может просто отобразить его в качестве DateTime, или что материя в TimeSpan.

Так что вам нужно добавить X-Values либо как DateTime или double, которые содержат значения, которые могут быть преобразованы в DateTime. Fomer является то, что я предпочитаю ..

Таким образом, вместо добавления секунды непосредственно добавить их в качестве смещения от заданного DateTime:

Изменить что-то вроде этого

series.Points.AddXY(sec, yValues); 

К этому:

var dt = new DateTime(0).AddSeconds(sec); 
series.Points.AddXY(dt, yValues); 

Теперь вы можете использовать строки форматирования даты и времени по мере необходимости ..:

chartArea.AxisX.LabelStyle.Format = "{mm:ss}"; 

Вы также можете добавить их doubles, что на самом деле вычисляются из DateTimes через ToOADate:

series.Points.AddXY(dt.ToOADate(), yValues); 

Но теперь вам придется установить ChartValueType.DateTime и, вероятно, также AxisX.IntervalType и AxisX.Interval, чтобы убедиться, что диаграмма получает право на форматирование ..:

s.XValueType = ChartValueType.DateTime; 
ca.AxisX.Interval = 5; 
ca.AxisX.IntervalType = DateTimeIntervalType.Seconds; 
ca.AxisX.LabelStyle.Format = "{mm:ss}"; 

Выберите значения, соответствующие вашим данным!

Примечание, что проблема с исходным кодом является то, что X-Valuesвнутренне всегда являютсяdoubles, но секунд не являются целыми числами в них, но дробные части; поэтому вам нужен какой-то расчет. Вот что делает ToOADate. Вот короткий тест, который показывает, что один второй фактически делает сумму, как OADate double:

enter image description here

Лучший добавить X-Values в DateTimes так вся дальнейшая обработка может полагаться на тип ..

Обновление Я только что увидел, что вы, наконец, добавили настоящий код на свой вопрос, и он использует Points.DataBindY. Боюсь, это не создаст значимых X-ценностей. Попытайтесь перейти на Points.DataBindXY! Конечно, X-Значения, которые вы связываете, также должны следовать правилам, которые я объяснил выше ..!

Вы можете сделать цикл над вашим массивом и преобразовать числа, как показано выше; вот простой пример:

int[] seconds = new int[5] { 1, 3, 88, 123, 3333 }; 
    double[] oaSeconds = seconds.Select(x => new DateTime(0).AddSeconds(x).ToOADate()) 
           .ToArray(); 
+0

Здравствуйте, @TaW, большое спасибо за ваш вклад. Я также думал о преобразовании его в Datetime, но таким образом я не знаю, как я могу отображать промежутки времени, которые превышают 24 часа. Возможно, вы также знаете, как я могу это сделать? Заранее спасибо – FriendlyGuy

+0

Вы имеете в виду часы, переходящие 23 вместо того, чтобы переносить на день? Нет, я не думаю, что для этого есть формат времени. Это imo будет составлять пользовательскую строку, и я думаю, вам придется помещать эти строки в CustomLabels. Это несколько сложно сделать. Или вы можете попытаться установить «AxisLabel» для каждой DataPoint, вызывая функцию, которую вы пишете. Вам нужно будет поэкспериментировать с Интервалом, чтобы показать подходящее количество этих ярлыков. – TaW

+0

Честно говоря, я не профессиональный программист, я просто делаю это в свое свободное время и использую его в университете для обработки данных. Поскольку диаграмма boxplot вычисляет, это обязательные значения на ее собственном уровне, я не думаю, что я могу установить AxisLabels вручную, поэтому мне, вероятно, понадобится настраиваемая строка. Не могли бы вы дать мне подсказку, как я могу это сделать?Это мне очень помогло, так как я не знаю, как я могу настроить строку :) – FriendlyGuy

Смежные вопросы